반응형

2438번 문제 : 별 찍기

https://www.acmicpc.net/problem/2438


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
using namespace std;
 
int main() {
    int inp;
    cin >> inp;
 
    for (int i = 0; i < inp; i++)
    {
        for(int j = 0; j < i + 1; j++)
        {
            cout << "*";
        }
        cout << endl;
    }
 
    return 0;
}
cs



메모: 

-endl 대신 cout "\n" 사용하면 4ms 빨라짐



2292번 문제 : 벌집

https://www.acmicpc.net/problem/2292


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
 
int main() {
    int inp;
    cin >> inp;
    int counter = 0;
    int num = 1;
 
    if (inp != 1)
    {
        while (inp > num)
        {
            num = num + 6 * counter;
            counter++;
        }
    }
    else
    {
        counter++;
    }
 
    cout << counter;
 
    return 0;
}
cs


메모: 

-반례 inp : 1때문에 inp !=1 조건문이 필요



1193번 문제 : 분수찾기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;
 
int main()
{
    int inp;
    cin >> inp;
        
    int total = 1;
    int row = 1;
    while (total < inp)
    {
        row++;
        total += row;
    }
 
    int col = inp - (total - row);
 
    if (row % 2 != 0)//odd
    {
        cout << row - col + 1 << "/" << col;
    }
    else //even
    {
        cout << col << "/" << row - col + 1;
    }
 
    return 0;
}
 
cs


10250번 문제 : ACM 호텔

https://www.acmicpc.net/problem/10250


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <vector>
#include <string>
using namespace std;
 
int main()
{
    int inp;
    cin >> inp;
 
    vector<string> result;
 
    while (inp > 0)
    {
        int h, w, n;
        cin >> h >> w >> n;
 
        string roomNum = "";
        int counter = 1;
        int leftovers = n;
 
        while (leftovers > h) 
        {
            counter++;
            leftovers -= h;
        }
 
        if (counter < 10)
        {
            roomNum += to_string(leftovers);
            roomNum += "0";
            roomNum += to_string(counter);
        }
        else
        {
            roomNum += to_string(leftovers);
            roomNum += to_string(counter);
        }
 
        result.push_back(roomNum);
 
        inp--;
    }
 
    for (auto i : result)
        cout << i << endl;
 
    return 0;
}
 
cs


1924번 문제 : 2007년

https://www.acmicpc.net/problem/1924


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
using namespace std;
 
int main(void) {
 
    string dayName[7= { "SUN" , "MON""TUE""WED""THU""FRI""SAT" };
    int month[13= { 0312831303130313130313031 };
    int totalDays = 0;
    int inputM, inputD;
 
    cin >> inputM >> inputD;
 
    for (int i = 0; i < inputM; i++)
        totalDays += month[i];
    totalDays += inputD;
    int leftover = totalDays % 7;
 
    cout << dayName[leftover];
 
    return 0;
}
cs



2775번 문제 : 부녀회장이 될테야

https://www.acmicpc.net/problem/2775


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
using namespace std;
 
int arr[15][14= { 0 };
 
int GetNum(int k, int n)
{
    if (k == 0)
        return arr[k][n];
    else
    {
        if (arr[k][n] != 0)
            return arr[k][n];
        else
        {
            for (int i = 0; i <= n; i++)
            {
                arr[k][n] += GetNum(k - 1 , i);
            }
            return arr[k][n];
        }
    }
}
 
int main() {
 
    for (int i = 0; i < 14; i++)
    {
        arr[0][i] = i + 1;
    }
 
    int inp;
    cin >> inp;
 
    while (inp > 0
    {
        int a, b;
        cin >> a >> b;
        cout << GetNum(a, b - 1<< endl;
 
        inp--;
    }
    
 
    return 0;
}
 
cs

메모:
-성능을 위해  메모라이제이션 사용


1475번 문제 : 방 번호

https://www.acmicpc.net/problem/1475


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
using namespace std;
 
int main()
{
    int set[10= { 0 };
    int inp;
    cin >> inp;
 
    if (inp == 0)
    {
        cout << "1" << endl;
        return 0;
    }
    else
    {
        while (inp > 0)
        {
            int temp = inp % 10;
            set[temp] ++;
            inp /= 10;
        }
 
        int maxSet = 0;
        for (int i = 0; i < 10; i++)
        {
            if (i == 6 || i == 9)
                continue;
 
            if (set[i] > maxSet)
                maxSet = set[i];
        }
 
        int sixNineSet;
        if ((set[6+ set[9]) % 2 == 0)
            sixNineSet = (set[6+ set[9]) / 2;
        else
            sixNineSet = (set[6+ set[9]) / 2 + 1;
        if (sixNineSet > maxSet)
            maxSet = sixNineSet;
 
        cout << maxSet << endl;
    }
 
    return 0;
}
 
cs


1475번 문제 : 카잉 달력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <vector>
using namespace std;
 
int GCD(int a, int b)
{
    if (a % b == 0)
        return b;
 
    return GCD(b, a % b);
}
 
int LCM(int a, int b)
{
    return (a * b) / GCD(a, b);
}
 
int main()
{
    int inp;
    cin >> inp;
 
    vector<int> result;
 
    while (inp > 0)
    {
        int M, N, x, y;
        cin >> M >> N >> x >> y;
 
        int counter = 1;
        int maxYear = LCM(M, N);
        while (true)
        {
            if (x > maxYear || (x - 1) % N + 1 == y)
                break;
 
            x += M;
        }
 
        if (x > maxYear)
            result.push_back(-1);
        else
            result.push_back(x);
 
        inp--;
    }
 
    for (auto i : result)
        cout << i << "\n";
 
    return 0;
}
 
cs


반응형

'C++ Algorithm > 백준 알고리즘 문제 풀이' 카테고리의 다른 글

소수 구하기  (0) 2019.02.13
정렬해보기  (0) 2019.02.10
문자열 사용하기 3  (0) 2019.02.05
문자열 사용하기 2  (0) 2019.02.03
문자열 사용하기  (0) 2018.11.27
반응형

2908번 문제 : 상수

https://www.acmicpc.net/problem/2908


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
 
using namespace std;
 
int ReverseNum(int inp)
{
    int reversedNum = 0, leftover = 0;
    while (inp > 0)
    {
        leftover = inp % 10;
        reversedNum = reversedNum * 10 + leftover;
        inp /= 10;
    }
 
    return reversedNum;
}
 
int main() {
    int a,b;
    int rA, rB;
    cin >> a >> b;
 
    rA = ReverseNum(a);
    rB = ReverseNum(b);
 
    int result = (rA > rB) ? rA : rB;
    cout << result;
        
    return 0;
}
cs


5622번 문제 : 다이얼

https://www.acmicpc.net/problem/5622


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
using namespace std;
 
int main() {
    string inp;
    cin >> inp;
    int totalTime = 0;
 
    for (int i = 0; i < inp.length(); i++)
    {
        int temp = (int)inp[i] - 65;
 
        if (temp < 15) {
            temp /= 3;
            totalTime += (temp + 3);
        }
        else if (temp < 19) {
            totalTime += 8;
        }
        else if (temp < 22) {
            totalTime += 9;
        }
        else {
            totalTime += 10;
        }
    }
    cout << totalTime;
 
    return 0;
}
cs


2941번 문제 : 크로아티아 알파벳

https://www.acmicpc.net/problem/2941


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
using namespace std;
 
int main() {
    string inp;
    cin >> inp;
    
    string arr[8= {"c=""c-""dz=""d-""lj""nj""s=""z="};
    int counter = 0;
    
 
    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        size_t pos = inp.find(arr[i], 0);
        while (pos != string::npos)
        {
            counter++;
            pos = inp.find(arr[i], pos + 1);
        }
    }
 
    cout << inp.size() - counter;
 
    return 0;
}
cs


메모: 

-배열의 길이는 size(), count(), length() 와 같은 함수로 구할 수 없음. (c++ 14기준)

 C 스타일의 sizeof(arr)/sizeof(arr[0] 로 구하거나 c++17 이상 부터 size(arr) 사용이 가능

-처음부터 container를 사용해야지 길이 구하는 함수를 사용할 수 있음






반응형

'C++ Algorithm > 백준 알고리즘 문제 풀이' 카테고리의 다른 글

정렬해보기  (0) 2019.02.10
규칙 찾기  (0) 2019.02.05
문자열 사용하기 2  (0) 2019.02.03
문자열 사용하기  (0) 2018.11.27
1차원 배열 사용하기  (0) 2018.11.27
반응형

1157번 문제 : 단어 공부

https://www.acmicpc.net/problem/1157


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <string>
using namespace std;
 
int main()
{
    int alphabet[26= { 0 };
    string str;
    cin >> str;
 
    for (int i = 0; i < str.length(); i++)
    {
        int ASCIInum = (int)str[i];
 
        //ASCII code 'A':65 ~ 'Z': 90      'a': 97 ~ 'z': 122
        if(ASCIInum>=65 && ASCIInum <=90)
            alphabet[(int)str[i] - 65++;
        else if(ASCIInum >= 97 && ASCIInum <= 122)
            alphabet[(int)str[i] - 97++;
    }
 
    int max = 0;
    int index = 0;
    bool isTheOnlyMax = true;
    for (int i = 0; i < 26; i++)
    {
        if (alphabet[i] > max)
        {
            max = alphabet[i];
            index = i;
        }
    }
 
    for (int i = 0; i < 26; i++)
    {
        if (index == i)
            continue;
 
        if (alphabet[i] == max)
        {
            isTheOnlyMax = false;
            break;
        }
    }
 
    if (isTheOnlyMax)
        cout << (char)(index + 65);
    else
        cout << "?";
 
    return 0;
}
cs


메모: 

-ASCII Table상에서 'Z' 다음은'a' 가 아님


1316번 문제 : 그룹 단어 체커

https://www.acmicpc.net/problem/1316


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
using namespace std;
 
int main()
{
    int num = 0;
    int counter = 0;
    cin >> num;
    while (num > 0
    {
        string input;
        bool flag = false//used to break nested loop
        cin >> input;
 
        if (input.length() > 2)
        {
            for (int i = 1; i < input.length(); i++)
            {
                if (input[i - 1!= input[i])
                {
                    for (int k = 0; k < i; k++)
                    {
                        if (input[i] == input[k])
                        {
                            flag = true;
                            break;
                        }
                    }
                    if (flag)
                        break;
                }
 
                if (i == input.length() - 1)
                    counter++;
            }
        }
        else
        {
            counter++;
        }
 
        num--;
    }
 
    cout << counter;
 
    return 0;
}
cs


메모: 

-이중루프(nested loop)를 빠져나오기 위해 bool 형식의 flag를 사용하고 있음



1152번 문제 : 단어의 개수

https://www.acmicpc.net/problem/1152


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
#include <sstream>
 
using namespace std;
 
int main() {
    string inp;
    getline(cin, inp);
    istringstream iss(inp);
    int counter = 0;
 
    string str;
    while (iss >> str)
    {
        counter++;
    }
    cout << counter << endl;
 
    return 0;
}
cs


메모: 

-C++string Split 할 수 있는 여러가지 방법들

http://www.martinbroadhurst.com/how-to-split-a-string-in-c.html

https://www.fluentcpp.com/2017/04/21/how-to-split-a-string-in-c/





반응형

'C++ Algorithm > 백준 알고리즘 문제 풀이' 카테고리의 다른 글

규칙 찾기  (0) 2019.02.05
문자열 사용하기 3  (0) 2019.02.05
문자열 사용하기  (0) 2018.11.27
1차원 배열 사용하기  (0) 2018.11.27
함수 사용하기  (0) 2018.11.18
반응형

루 1.5.9버전 업데이트 및 최적화 작업, IL2CPP빌드


이번에 Lu 를 1.5.9버전으로 업데이트하면서 최적화 중심으로 작업을 진행하였다.

최적화 작업을 이전에도 여러번 했는데도 불구하고 최적화 작업은 항상 할게 많다...


이번 업데이트는 외관상 큰 변화는 없지만 퍼포먼스는 조금더 개선됬다고 생각한다.


1) 게임플레이 개선, 수정 사항


Planet Monster AI수정: 기존에는 중앙에 고정시켰는데 어색해 보여서 움직이게끔 바꿨다.

초반에 보스가 스폰될때 Dissolve효과가 있다.

우측상단에 FPS 표시





2) Editor Log활용: Apk 용량 줄이기


Console창 구석에 있는 아이콘을 오른쪽 클린하면 Open Editor Log라는 창이 있다.

이 창을 열면 Text형식의 Log창이 뜬다.



그리고 프로젝트를 빌드 후 Editor Log창을 클릭하면 Log내용에서 Build Report을 확인할 수 있다. 

(꼭 빌드 후에 해야지 Build Report Log가 남는다)


여기서 자신의 프로젝트가 어느 부분에서 용량을 차지하는지 확인 할 수있다. 

대부분 프로젝트가 그렇듯이 용량을 가장 많이 자치하는 부분 중 하나는 텍스쳐일것이다.

내 프로젝트도 가장 용량을 많이 차지한 부분이 텍스처이다



사진을 보면 알 수 있듯이 Particle Effect에 들어가는 Texture그리고 보스몹에 들어가는 tga형식의 Texture가 지나치게 높은것을 확인 할 수 있다. 이걸 최적화하면 된다.

최적화하는 가장 쉬운 방법 중 하나는 Unity가 제공하는 기능중 하나인 Texture Compression 기능이다.



Texture를 Compress 하게 되면 용량이 많이 줄어든다.

참고로 Texture를 Compress하려면 Texture파일이 높이와 폭이 4^n꼴이어야한다 ex) 512x512, 1024x512 등등

그렇기 때문에 만약 Texture사이즈가 4^n꼴이 아니면 이것부터 수정하는 작업을 해야한다. 

(참고로 Texture크기를 수정하면 Texture를 사용하고 있는 GameObject도 같이 바뀌기 때문에 꼭 확인해야한다)

(또 지나치게 Compress를 많이하면 Texture가 Blur하게 보이기 때문에 적절한 수치를 찾아야한다)

(Font도 용량을 은근히 많이 먹는다. 종류가 다른 Font가 지나치게 많이 사용되면 APK 용량이 커질수 있다는걸 알 수 있다...)


아무튼 Texture의 크기를 수정하고 적절하게 Compress해주면 


용량이 확 줄어든다! 

내 프로젝트는 62MB -> 46MB으로 줄어들었다



3) IL2CPP빌드


IL2CPP이란 말그대로 IL(Intermediate Language, 중간어) 를 CPP(c++)로 바꿔주는 빌드이다.

더 자세한 내용은 다음 링크에서 보면 된다.

https://blogs.unity3d.com/kr/2015/09/22/kr-csharp-compile-il2cpp/


IL2CPP빌드를 왜 하냐? 여러가지 이유가 있지만 

유니티 공식 문서에 따르면 

 IL2CPP는 Unity 프로젝트의 성능, 보안 및 플랫폼 호환성을 개선하는 등의 용도로 사용됩니다. "

라고 한다...


APK를 크랙할때 크랙프로그램을 통해 프로젝트를 뜯을 수 있는데 

IL로 빌드된 APK같은 경우 보안에 최약하다고 한다. 

쉽게 뜯기고 코드도 쉽게 찾을 수 있다고 한다...

하지만 IL2CPP로 빌드하면 뜯어도 알아보기 힘든 형태로 있기때문에 크랙하기 더 복잡하다고 한다. 

유명한 게임아니면 시간투자해서 크랙하는것 자체가 시간낭비기 때문에

IL2CPP로 빌드하는것 자체가 나름 보안을 강화하는 역할을 한다.


내 프로젝트는 자체가 작음에도 불구하고

빌드시간이 IL2CPP로 10분정도 걸린것 같다. (Mono로 했을때 2분)

(참고로 빌드한 컴퓨터 사양이 낮다. 그래서 더 오래걸린 것도 있다 

컴퓨터 사양 : i3 4179, gtx960,  ram 8g)

규모가 정말 크다면 빌드하는데 몇시간 걸리지 않을까 싶다. 

추가) 처음 IL2CPP빌드했을때 10분정도 걸렸지만 그 이후에 다시 한번 빌드하니 3분정도 걸린것 같다


현재 이 프로젝트가 원래 무겁지 않은 탓인지 Mono이나 IL2CPP로 빌드 했을때 플레이어가 느끼는 성능차이는 없다고 생각이든다.

나름 현재 기준으로 오래된 기종인 갤럭시 S3에서도 큰 무리없이 돌아갈 정도로 프로젝트가 가볍기 때문이다.

그래서 IL2CPP가 내 프로젝트에 큰 의미가 있을까 싶었지만 이것보다 큰 프로젝트에서는 성능의 차이를 느낄 수 있을 것이다.

그나마 내 프로젝트에서는 체감되는 부분은 UI를 다룰때 살짝(?) 차이가 있다.

현재 Dotween 이라는 에셋을 사용하여 UI Tweening동작을 하고 있는데 게임이 처음 로딩된 후 초반에 부드럽게 Tweening이 이루어지지 않고 프레임드랍이 조금씩 발생했다. 하지만 이번에 IL2CPP로 빌드한 후에는 초반에도 부드럽게 Tweening동작이 이루어진다.





반응형
반응형

유니티 엔진 팁 1탄

(2019.01.09 작성일 기준)



1. 유니티 관련 커뮤니티 사이트


네이버 카페 - 유니티허브

https://cafe.naver.com/unityhub


네이버 카페 - 인디게임 개발자 쉼터

https://cafe.naver.com/indiedev



2. 유니티 홈페이지


공식 유니티 홈페이지

https://unity3d.com/kr


에셋스토어 : 에셋 활용할때는 에셋스토어

https://www.assetstore.unity3d.com/kr/#!/home


유니티 엔진 API (Documentation) : 개발할때 가장 많이 사용하는 문서중 하나, 버전에 맞게 사용할 필요가 있다!

https://docs.unity3d.com/Manual/ManualVersions.html


3. 유니티 관련 영상 및 강의


Brackeys 유튜브 유니티 강의 : 유투브 유니티 강의중 가장 깔끔하고 알아듣기 쉽게 알려주는곳!

https://www.youtube.com/channel/UCYbK_tjZ2OrIZFBvU6CCMiA


NDC 유튜브: Nexon Developer Conference를 녹화하고 공개한 곳, 은근히 볼만하다

https://www.youtube.com/channel/UC3ZjKSQX9JJRCjw3aSrBXSg


인프런: 유니티뿐만아니라 다른 프로그래밍 언어 전반을 알려주는곳. 사실 유니티 강의는 들어본적이 없어서 강의가 좋은지는 잘모르겠다.

https://www.inflearn.com/


ASK GameDev : 게임 개발 전반적인 것들에 대해 쉽게 설명하고 있는 유튜브 채널

https://www.youtube.com/channel/UCd_lJ4zSp9wZDNyeKCWUstg





반응형
반응형

네트워크 RPG게임 'Raid' 개발일지 6


정말 오랜만에 레이드 개발일지를 올린다!

5번째 개발일지를 올린지 벌써 2주가 되었다...

핑계를 대자면 방학이지만 아르바이트, 계절학기 까지 있다보니까 생각보다 시간이 없다... ㅠㅠ

또 최근에는 루 업데이트 및 최적화하는데 재미(?)가 들려서 이 프로젝트에 조금 소흘해진건 사실이다...

현재는 루 업데이트가 어느정도 만족스럽게 이루어졌고 이제 다시 레이드에 집중할때가 된것 같아서 다시 시작하게 되었다.


일단 가장 큰 업데이트 사항은 보스에 여러가지 공격 패턴을 만들었다

지금은 총 4개의 공격패턴을가지고 있다.

지금 현재 공격 자체가 조금 단순한 느낌이 없지않아 있는데 앞으로 좀 더 다이내믹하게 수정할 생각이다.




앞으로 계획은 다음과 같다

1. 공격패턴 추가 및 다이내믹하게 변경!  (이게 가장 중요한데 난이도가 가장 높을것 같다)

2. 맵 다시 제작 후 Mesh Bake해서 최적화

3. 게임 State 추가 : 현재는 바로 시작하는 형태지만 이제는 시작/게임중/게임종료등의 State를 넣어야한다. 플레이어 모두가 들어오면 시작하고 모두 죽었을시 게임 종료하는 형식으로 현재는 생각하고 있다.

4. 카메라: 좀더 부르덥게 회전 그리고 상하로 스와프시 카메라의 높이까지 변경




반응형
반응형

유니티) 보스의 공격 범위 표시


많은 RPG게임에서 보스전을 할때 공격 범위를 미리 표시한다.

프로젝트 루에서도 적이 공격 모션을 취할때 미리 공격 범위를 표시한다.

공격 범위를 표시하는데 여러가지 방법이 있다.

루에서는 두가지 방법을 사용하고 있다.


1. 공격범위를 나타내는 게임 오브젝트 생성 

말 그대로 범위를 나타내는 게임 프리팹을 Instantiate 하는 방식이다. 

(만약 공격범위를 여러개 표시할 경우 오브젝트 풀링을 사용하는게 현명하다)




2. 유니티 프로젝터 (Projector)

Projector는 빔 프로젝터처럼 Material을 쏴주는 컴포넌트이다.

Texture를 가진 Projector를 쏴주면 Texture가 부딪히는 오브젝트에 표시된다.



그냥 1번 방식으로 오브젝트를 생성하면 되지 뭐하러 프로젝터를 사용하냐고 생각할 수도 있지만

지형이 평평하지 않거나 지형의 끝자락에서는 프로젝터를 사용하는게 더 깔끔하다.



루에서는 위에서 아래로 프로젝터가 쏘는 형식이다

공격의 종류에 따라 프로젝터가 parameter값들의 변화를 줘 표시 범위를 다르게 하고 있다

아래 스크린샷처럼 프로젝터를 사용했을때 지형끝에 있는 원이 자연스럽게 짤려서 보인다



결론

- 1번 2번 방식을 상황에 맞게 활용할 필요가 있다.

- 공격 범위를 많이 표시해야되는 경우 오브젝트풀링을 사용하는게 현명하다. 


다음은 루에서 한 보스의 공격 패턴 중 하나이다. 여기서 ObjectPoolingManager의 메서드를 콜해 프로젝터를 SetActive(true)하는 방식을 사용하고 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    IEnumerator StateCastCrossAttack()
    {
        float randomY = Random.Range(0, 360f);
        crossAttackRotation = new Vector3(90f, randomY, 0f);
        Quaternion quaternion = Quaternion.Euler(crossAttackRotation);
 
        int fieldOfView = 100;
        var projector = ObjectPoolingManager.instance.SpawnProjectorFromPool("CrossProjector", transform.position, fieldOfView);
        projector.transform.rotation = quaternion;
        projector.GetComponent<SetActiveFalseOverTime>().SetActiveFalse(2.5f);
 
        float coolTime = 2f;
        yield return new WaitForSeconds(coolTime);
        animator.SetTrigger("castAttack");
 
        StartCoroutine(WaitForAttackToEnd());
        yield return null;
    }
cs


-하지만 여기서 조심해야할 부분은 2번 방식의 프로젝터를 사용했을떄 batching수, 즉 드로우콜(Draw Call)이 프로젝터당 1개씩 증가한다는것이다. 그래서 여러개의 프로젝터를 생성할때 순간적인 프레임드랍이 발생할 수 있다.





반응형
반응형

유니티) FPS와 관련된 Trouble



오늘 갑자기 Lu 의 게임 최적화때문에 FPS(Frame Per Second)가 어떻게 되는지 확인했다

그전에는 단순히 수치보고 너무 낮지만 않으면 잘돌아간다고 생각하고넘어갔던 문제였는데

앞으로 개발할때 주의해야겠다는 부분을 발견했다


먼저 Lu 프로젝트는 Unity 5.6 버전에서 개발되었다

또한 맥북프로로 개발된 프로젝트이다 


문제를 살펴보자면 Editor창에서 Maximum on Play상태에서의 FPS가 30언저리 밖에 나오지 않는다. 

하지만 Maximum on Play를 활성화시키면 FPS가 100까지 오르고 Batching이 갑자기 많이 발생하는 상황이 나타나면 줄어든다... 어쨋든 FPS가 100을 넘고 그냥 단순히 생각해보면 아 프레임이 잘나오네? 이렇게 생각할 수 있는데 FPS에 따라 플레이어의 움직임에 영향을 미치는것 같은 느낌이 들었다...


1) 다른 인스팩터창과 같이 Game Play를 할때 (Maximum On Play 비활성화) 

FPS 30 언저리




1) Maximum On Play 활성화 할때 

FPS 60 유지 (targetframe = 60으로 설정)



문제점은 FPS에 따라 Move되는 거리가 다르게 보이는 것이었는데 FPS가 높으면 더 천천히 그리고 반대로 FPS가 더 빨리 이동한는 점이다... 즉, FPS가 다를때마다 플레이어의 이동속도가 다르게 나타나고 있었다!...


처음에는 스크립상의 문제라고 생각이 됬다.

기본적인 움직임 스크립트는 다음과 같이 구성되어 있는데

1
2
3
4
5
6
7
8
9
10
11
12
13
    void Move(float hor, float ver)
    {
        if (!acting) //when basic movement
            playerSpeed = SPEED_DEFAULT + (float)SaveManger.instance.SpeedLV * 0.08f;
        else // when dash , skill attacks, etc
            playerSpeed = (SPEED_DEFAULT - 3f) + (float)SaveManger.instance.SpeedLV * 0.08f;
 
        Vector3 targetDirection = new Vector3(hor, 0f, ver);
        targetDirection = CameraManager.instance.mainCam.transform.TransformDirection(targetDirection);
        targetDirection.y = 0.0f;
        movement = targetDirection.normalized * playerSpeed * Time.deltaTime;
        playerRigidbody.MovePosition(transform.position + movement);
    }
cs

Rigidbody의 MovePosition 함수를 이용한 움직임 스크립트이다.


하지만 스크립트상으로는 큰 문제점이 보이지 않는다. 왜냐하면 direction을 normaize(정규화)한 이후에 Time.delaTime값을 곱하는 것 자체가 프레임의 높고 낮음과 상관없이 시간당 일정한 거리를 움직이게 하는 역할을 하기때문이다. 

(처음에는 MovePostion함수 자체의 문제인가 의심을 했지만 그것도 당연히 아니었다)


혹시 안드로이드에 앱에서는 어떻게 FPS가 나오는지 궁굼해서 FPS실험을 한 결과 60FPS에 고정되어있다

(Document에서는 Mobile의 경우 주로 30FPS에 맞춘다고 써 있는데 이게 기종에 따라 지원하는 FPS가 다르)

https://docs.unity3d.com/ScriptReference/Application-targetFrameRate.html



그래서 결국 이 문제를 해결하고자

1
Application.targetFrameRate = 60
cs

프레임을 60으로 고정시킨 후에 변화가 있는지 확인해보았다. 하지만 역시 Maximum on Play에서만 60FPS가 고정되었고 Maximum on Play를 끈 상태에선 계속 말도 안되게 낮게 나온다.


왜 이런 현상이 나타날까 열심히 구글링과 테스트한 결과 아주 허무한 결론이다.


한줄로 정리하자면 그냥 

"맥북에서 유니티 5.6 의 버그인것 같다"


맥북프로에 말고 윈도우 데스크탑에서 2017.3 버전으로 테스트한 결과 Maximun on Play 여부와 상관없이 프레임 드랍현상이 일어나지 않는다.

또한 Profiler의 Record기능이 editor상에서 프레임드랍에 영향을 준다. 그래서 Record기능을 끄면 프레임이 오른다... 30까지만...

그래서 이 프로젝트의 게임플레이를 확인할때는 Maximun on Play 를 키고 확인해야하는 번거로움이 있을것 같다... 

그리고 앞으로 모바일 프로젝트할때는 휴대폰이 30FPS, 60FPS인점을 감안해서 targetFrameRate을 지정한 후에 테스트하는게 좋을것 같다.




추가) 2019. 01. 18

최근에 윈도우 컴퓨터에 5.6.6버전을 받아서 Lu 프로젝트를 테스트한 결과 프레임 드랍현상이 나타나지 않았다.

유니티 버전이랑 상관없이 맥북에서 발생하는 버그로 보인다.


추가) 2019. 06. 05

Application.targetFrameRated을 지정시켜도 이는 에디터에 영향이 없다.

결론: 단순한 유니티 에디터의 버그이다.

반응형

+ Recent posts