목차

반응형

1. 개요

2. 블루스택 설치

3. APK 설치

4. ADB 로그캣 연동

5. 유니티 빌드 오류

 

 

 

 

 

 

 

 

 

1. 개요

사내 QA 팀은 빌드한 게임 테스트를 위해서 녹스나 블루스택을 사용한다. 이를 앱플레이어라고 하는데

만약 당신의 개발 환경이 mac이라면 녹스와 블루스택중 블루스택을 권장한다. 그 이유는 녹스의 경우 mac에서 사용하기 불편하다. 그리고 딱 보면 녹스의 window 버전 하고 mac 버전하고 비교해보면 mac 버전은 정말 초라하다.

여튼 오늘은 블루스택을 설치해서 당신의 게임을 구동하는 부분까지 안내하도록 하겠다.

 

 

 

2. 블루스택 설치

www.bluestacks.com/download.html

 

윈도우 OS에 따라 선택해서 블루스택 설치 파일을 다운로드한다.

참고로 맥과 동일한 환경으로 설치하고 싶다면 Android 64 Bit를 설치하자(mac은 64 bit밖에 없음)

 

 

 

최초 실행 시 위와 같은 화면을 볼 수 있다.

 

 

3. APK 설치

유니티에서 게임을 빌드하면 생기는 APK를 블루스택에 설치하려면 단순히 더블클릭을 해도 되고 또는 APK를 드래그해서 블루스택에 넣어보자.

그러면 내 게임에 설치한 게임이 생기면서 실행이 가능하다.

 

 

4. ADB 로그캣 연동

 

ADB 로그캣 연동하는 방법도 굉장히 쉽다.

 

 

우측 햄버거 버튼 > 설정

 

 

설정 > ADB 사용 체크

 

 

바로 ADB에 에뮬레이터로 잡힌다.

adb logcat -s Unity 해주면 된다.

 

 

5. 유니티 빌드 오류

유니티에서 빌드한 앱이 블루스택에서 그냥 꺼져버리는 경우가 있다.

그런 경우는 빌드 설정을 아래와 같이 해주면 된다.

 

Scripting Backend를 IL2CPP로

Target Architecutres의 두개를 다 체크해주자.

 

그리고 다시 해보면 잘 작동한다.

 

블루스택 bit 환경 Scripting Backend ARMv7 ARM64 구동 여부
32 bit IL2CPP O O O
32 bit IL2CPP X O X
32 bit IL2CPP O X O
32 bit Mono     X
64 bit IL2CPP
O O O
64 bit IL2CPP X O X
64 bit IL2CPP O X O
64 bit Mono     X

빌드별로 구동 되는지 안되는지 여부를 확인해봤는데 위과 같은 결과가 나왔다. 참고하자

반응형
반응형

유니티에서 빌드를 하다 보면 아래와 같은 오류가 발생할 때가 있다.

Failed running C:\Program Files\2019.4.5f1\Editor\Data\il2cpp/build/deploy/net471/il2cpp.exe --convert-to-cpp --emit-null-checks --enable-array-bounds-check --dotnetprofile="unityaot" --compile-cpp --libil2cpp-static --platform="Android" --architecture="ARMv7" --configuration="Release" --outputpath="C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\assets\bin\Data\Native\armeabi-v7a\libil2cpp.so" --cachedirectory="C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Assets\..\Library\il2cpp_android_armeabi-v7a/il2cpp_cache" --additional-include-directories="C:/Program Files/2019.4.5f1/Editor/Data/PlaybackEngines/AndroidPlayer/Tools\bdwgc/include" --additional-include-directories="C:/Program Files/2019.4.5f1/Editor/Data/PlaybackEngines/AndroidPlayer/Tools\libil2cpp/include" --tool-chain-path="C:/Program Files/2019.3.15f1/NDK/android-ndk-r19" --profiler-report --map-file-parser="C:/Program Files/2019.4.5f1/Editor/Data/Tools/MapFileParser/MapFileParser.exe" --directory=C:/Users/user/Desktop/workspace/SuperHeadLeague-master/Temp/StagingArea/assets/bin/Data/Managed --generatedcppdir=C:/Users/user/Desktop/workspace/SuperHeadLeague-master/Temp/StagingArea/Il2Cpp/il2cppOutput 

stdout:
Building libil2cpp.so with AndroidToolChain
	Output directory: C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\assets\bin\Data\Native\armeabi-v7a
	Cache directory: C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Library\il2cpp_android_armeabi-v7a\il2cpp_cache
ObjectFiles: 371 of which compiled: 0
Total compilation time: 259 milliseconds.
il2cpp.exe didn't catch exception: Unity.IL2CPP.Building.BuilderFailedException: C:\Program Files\2019.3.15f1\NDK\android-ndk-r19\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++ @"C:\Users\user\AppData\Local\Temp\tmp5F14.tmp" -o "C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Library\il2cpp_android_armeabi-v7a\il2cpp_cache\linkresult_E7F6115F0E77C4908A52DED5466D075E\libil2cpp.so" -shared -Wl,-soname,libil2cpp.so -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--gc-sections -Wl,--build-id -stdlib=libc++ -static-libstdc++ -target armv7-linux-androideabi19 -Wl,--wrap,sigaction -llog -rdynamic -fuse-ld=gold.exe

C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5065: error: undefined reference to 'Presto_getBatterylife'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5076: error: undefined reference to 'Presto_getCountry'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5076: error: undefined reference to 'Presto_getCountry'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5065: error: undefined reference to 'Presto_getBatterylife'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5899: error: undefined reference to 'Presto_UUID'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5888: error: undefined reference to 'Presto_UnityInit'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5899: error: undefined reference to 'Presto_UUID'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5888: error: undefined reference to 'Presto_UnityInit'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)


   ��ġ: Unity.IL2CPP.Building.CppProgramBuilder.PostprocessObjectFiles(HashSet`1 objectFiles, CppToolChainContext toolChainContext)
   ��ġ: Unity.IL2CPP.Building.CppProgramBuilder.Build(IBuildStatistics& statistics)
   ��ġ: il2cpp.Program.DoRun(String[] args, List`1 foundAssemblies)
   ��ġ: il2cpp.Program.Run(String[] args, Boolean setInvariantCulture)
   ��ġ: il2cpp.Program.Main(String[] args)
stderr:

���� ���� ����: Unity.IL2CPP.Building.BuilderFailedException: C:\Program Files\2019.3.15f1\NDK\android-ndk-r19\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++ @"C:\Users\user\AppData\Local\Temp\tmp5F14.tmp" -o "C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Library\il2cpp_android_armeabi-v7a\il2cpp_cache\linkresult_E7F6115F0E77C4908A52DED5466D075E\libil2cpp.so" -shared -Wl,-soname,libil2cpp.so -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--gc-sections -Wl,--build-id -stdlib=libc++ -static-libstdc++ -target armv7-linux-androideabi19 -Wl,--wrap,sigaction -llog -rdynamic -fuse-ld=gold.exe

C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5065: error: undefined reference to 'Presto_getBatterylife'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5076: error: undefined reference to 'Presto_getCountry'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5076: error: undefined reference to 'Presto_getCountry'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5065: error: undefined reference to 'Presto_getBatterylife'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5899: error: undefined reference to 'Presto_UUID'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5888: error: undefined reference to 'Presto_UnityInit'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5899: error: undefined reference to 'Presto_UUID'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5888: error: undefined reference to 'Presto_UnityInit'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)


   ��ġ: Unity.IL2CPP.Building.CppProgramBuilder.PostprocessObjectFiles(HashSet`1 objectFiles, CppToolChainContext toolChainContext)
   ��ġ: Unity.IL2CPP.Building.CppProgramBuilder.Build(IBuildStatistics& statistics)
   ��ġ: il2cpp.Program.DoRun(String[] args, List`1 foundAssemblies)
   ��ġ: il2cpp.Program.Run(String[] args, Boolean setInvariantCulture)
   ��ġ: il2cpp.Program.Main(String[] args)

UnityEngine.Debug:LogError(Object)
UnityEditorInternal.Runner:RunProgram(Program, String, String, String, CompilerOutputParserBase)
UnityEditorInternal.Runner:RunManagedProgram(String, String, String, CompilerOutputParserBase, Action`1)
UnityEditorInternal.IL2CPPBuilder:RunIl2CppWithArguments(List`1, Action`1, String)
UnityEditorInternal.IL2CPPBuilder:ConvertPlayerDlltoCpp(Il2CppBuildPipelineData, String, String, Boolean)
UnityEditorInternal.IL2CPPBuilder:Run()
UnityEditorInternal.IL2CPPUtils:RunIl2Cpp(String, String, IIl2CppPlatformProvider, Action`1, RuntimeClassRegistry)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)

 

위는 오류 전문이다.

 

 

C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5065: error: undefined reference to 'Presto_getBatterylife'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5076: error: undefined reference to 'Presto_getCountry'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5076: error: undefined reference to 'Presto_getCountry'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5065: error: undefined reference to 'Presto_getBatterylife'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5899: error: undefined reference to 'Presto_UUID'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5888: error: undefined reference to 'Presto_UnityInit'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5899: error: undefined reference to 'Presto_UUID'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5888: error: undefined reference to 'Presto_UnityInit'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
C:\Users\user\Desktop\workspace\SuperHeadLeague-master\Temp\StagingArea\Il2Cpp\il2cppOutput/GPresto_iOS.cpp:5910: error: undefined reference to 'Presto_UserType'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

오류가 굉장히 길어서 도대체 어디가 문제인가 싶을 텐데 이 부분만 보면 된다. undefiend undefined reference to ~~~

해당 부분이 안드로이드에서 호출하려고하니 정의가 없어서 빌드를 못하겠다는 것이다.

 

나 같은 경우는 경로에 써있는 라이브러리가 문제를 일으키는 것이다.

고맙다 GPresto... 덕분에 제 시간을 날렸어요!

반응형
반응형

1. 개요
2. Transform, Rigidbody 방식 차이
3. Transform 방식으로 포물선 운동 구현

3.1 Tween 
3.2 단순 함수
3.3 떨어지는 방향 보도록 하기

4. Rigidbody 방식으로 포물선 운동 구현

4.1 포물선 운동 물리 공식 이해
4.2 도착지점 알고 발사 각도 알 때
4.3 도착 시간 알고 각도 알 때
4.4 Rigidbody 방식의 한계 - 중력이 정해져 있다
4.5 중력가속도를 바꿔서 투사체마다 다른 발사 방식 적용하기 
4.6 떨어지는 방향 보도록 하기

5. 결론과 요약 

 

 

 

 

 

 

 

 

 

 

 

 

1. 개요 

유니티로 게임을 만드는 사람이라면 한번쯤은 접해보고 포물선 운동 공식을 찾아보고 뭔개소리지 하며 절망했을만한 주제에 대해서 다뤄보도록 하겠다.

다양한 포물선 운동을 나타내는 방식과 코드에 대해서 작성해보았다. 나도 배워가는 단계라서 충분히 부족하지만 그나마 어느정도 이해는 한 상태로서 처음부터 배우고자 하는 사람에게 도움이 되고자 글을 써본다.

포물선 운동에 관한 포괄적인 내용정리를 목표로 글을 써봤다.

 

 

 


2. Transform, Rigidbody 방식 차이 

그 전에 먼저 유니티의 물리 엔진을 사용한다는 것에 대해서 이해를 해야한다.

유니티에서 게임 오브젝트를 이동하는 방식은 크게 두 가지가 있다.

첫번째는 Transform을 기반으로 움직이는 방식

transform.poisiton = transform.poisiton + Vector3.one; 을 행하게 되면 오브젝트가 순간이동을 하게 된다. 이를 반복적으로 행하면 연속적으로 이동하는 것 처럼 보이는데 그 원리를 이용하여 오브젝트를 움직이는 것 이다. 이런 방식을 Transform 기반으로 움직인다고 칭한다.

 

두 번째는 Rigidbody를 이용해서 움직이는 것이다.

오늘의 주제인 유니티 엔진의 물리를 이용해서 움직인다고 생각하면 된다.

Rigidbody.addforce(Vector3.one); 을 행하게 되면 물체가 물리작용을 받아서 움직이게 된다.

 

두 방식은 작게 봤을때는 기호의 차이처럼 보이지만 상당한 차이를 가지고 있으며 여기서 어떠한 방식으로 접근하냐에 따라 추후에 문제가 발생할 수도 있고, 발생한 문제를 해결해나가는 양상은 전혀 다르게 전개된다.(즉 여기서 내가 어떤 방식을 써야하는지 잘 골라라 이말이야)

 

간단한 예를들어 아래 글은 유니티 트레일 작동 방식에 대한 글 인데 Transform 이동방식과 Rigidbody 이동방식 차이에 따라 트레일이 생성되냐 안되냐 차이가 생긴다.

ajh322.tistory.com/265

 

유니티 트레일 움직여도 작동안할때

유니티 트레일에는 2개의 Scaling Mode가 있다. Transform과 Rigidbody이다. Transform Transform은 트레일이 붙어있는 오브젝트가 translate로 움직일 때 트레일이 발생한다. Rigidbody Rigidbody는 트레일이 붙..

ajh322.tistory.com

 

 

 

3. Transform 방식으로 포물선 운동 구현

Transform 방식으로 오브젝트를 움직이는 방식으로 이동하는 경우에 대해서 살펴보고 특징과 어떤 코드를 사용해야 포물선 움직임을 구현할 수 있는지 알아보자.

 

특징 1 : 유니티 물리엔진인 Rigidbody를 사용하지 않고 직접 움직이면 유니티 엔진의 한계없이 게임을 만들 수 있다.(여기서 말하는 한계란 유니티 물리 엔진을 활용하기 시작하면 복잡한 구현을 할 때마다 더욱 큰 난관에 부딪힌다는 말이다. 만약에 움직임을 addforce로 구현한다고 생각해보자, 이후 공기저항에 따른 이동속도 감소, 회전을 줘야할때 자체적인 스크립트가 아닌 유니티 Rigidbody 방식에서 해결하려면 미세한 컨트롤이 힘들어진다.)

 

특징 2 : 이동 단위(속도)가 큰 경우 충돌 판정이 정상적으로 이뤄지지 않음, 일반적으로 생각하는 물리적 결과와는 다른 결과가 나올 수 있음, 트리거 Enter 및 Collision 이벤트가 정상적으로 작동하지 않을 수 있음.

왼쪽과 오른쪽은 단순히 translate 해주는 크기의 차이(속도)로 인해서 발생하는 문제다.

둘다 텔레포트 하느 방식으로 이동하다보니 벽보다 이동속도가 빠른 경우 벽을 뚫고 지나가 버리는 경우가 허다하다.

이런 경우는 자체적으로 Collision 및 Enter를 판별하기 위하여 이동할때마다 물체간의 좌표에 대한 정보를 확인하여 해당 이벤트를 스스로 처리하는 시스템을 구현해야한다.

 

 

 

3.1 Tween

Transfom 이동방식중 한가지인 Tween 방식이다.

Tween을 모르는 분을 위해서 간단히 설명하자면 iTween, Dotween과 같은 라이브러리가 있는데 흔히 오브젝트를 부드럽게 이동하는 것을 구현하기 위해 IEnumerator를 위치를 이동해주는 것을 구현해주는데 그런 기능을 코드 한줄로 구현할 수 있도록 도와주는 유틸리티다.

그리고 Tween에는 보통 포물선 운동을 구현할 수 있는 함수가 내장되어있다.

 

Dotween의 경우 DOPath라는 함수를 사용하여 포물선 운동을 시각적으로 표현할 수 있다.

 

 void Start()
    {
        Vector3 firstPos = transform.position;
        Vector3 secondPos = firstPos + new Vector3(5, 5, 0);
        Vector3 thirdPos = firstPos + new Vector3(10, 0, 0);
        transform.DOPath(new[] {secondPos, firstPos+Vector3.up, secondPos + Vector3.left * 2, thirdPos, secondPos + Vector3.right * 2, thirdPos + Vector3.up}, 1f,PathType.CubicBezier).SetEase(Ease.Unset);
    }

위와 같은 코드를 사용하면 된다. 코드 사용방법은 Tween 라이브러리마다 다르다.

 

위의 운동이 어색해보이는 이유는 속도가 처음에 빨랐다가 최고점에서 가장 느렸다가 마지막에 빨라지는 효과를 넣어줘야하는데 그 부분을 넣어주지 않아서 그렇다.

Easing이라는 옵션을 넣어줘야하는데 포물선에 적합한 Easing이 없어서 함수를 직접 구현해줘야하는데 요청이 있으면 해당 부분을 구현해서 올리도록 하겠다.

 

 

3.2 단순 함수

직접 정의한 공식을 사용하여 함수형태로 움직이는 수식을 만들어서 처리하는 것이다.

어찌보면 Tween과 비슷한 처리 방식이지만 Tween에서 해주는 함수를 직접 정의해서 돌려주는 느낌이다.

 

    private Vector3 startPos, endPos;
    //땅에 닫기까지 걸리는 시간
    protected float timer;
    protected float timeToFloor;
    
    
    protected static Vector3 Parabola(Vector3 start, Vector3 end, float height, float t)
    {
        Func<float, float> f = x => -4 * height * x * x + 4 * height * x;

        var mid = Vector3.Lerp(start, end, t);

        return new Vector3(mid.x, f(t) + Mathf.Lerp(start.y, end.y, t), mid.z);
    }

    protected IEnumerator BulletMove()
    {
        timer = 0;
        while (transform.position.y>=startPos.y)
        {
            timer += Time.deltaTime;
            Vector3 tempPos = Parabola(startPos, endPos, 5, timer);
            transform.position = tempPos;
            yield return new WaitForEndOfFrame();
        }
    }

    private void Start()
    {
        startPos = transform.position;
        endPos = startPos + new Vector3(5, 0, 0);
        StartCoroutine("BulletMove");
    }

 위와 같다. (gist.github.com/ditzel/68be36987d8e7c83d48f497294c66e08)

필요한 변수는 시작지점, 착지지점, 높이, 걸리는 시간이다.(현재 수식에서는 1초로 고정)

 

해석

위의 식을 분석해보고 그에 대한 해석을 나름 해보았는데 궁금하면 읽어보자(패스해도 무방)

위 식에서 필요한 변수를 다시한번 생각해보자.

 

시작지점, 착지지점, 높이, 걸리는 시간

이 식이 갖는 특이한 점이라면 포물선 운동을 구현하는데 사인함수와 코사인함수 그리고 각도 정보가 없다는 것이다.

어떻게 그것이 가능할까?

 

return new Vector3(mid.x, f(t) + Mathf.Lerp(start.y, end.y, t) mid.z); 부분을 보자.

여기서 두 부분으로 나눌 수 있다.

x,z축 그리고 y축이다.

x,z축은 앞과 뒤를 나타내는 평면좌표계고 y축은 높이를 나타낸다.

 

x, z 값은 직선운동처럼 시작지점부터 끝지점까지 Lerp함수를 이용해서 1초를 기준으로 0초면 시작지점, 1초면 끝지점이 되도록 값을 할당받는다.

그리고 y값은 직접 정의한 f(t)함수를 이용해서 받아오는데(y값 뒤의 Mathf.Lerp(start.y, end.y, t)는 높이가 다른 경우를 위해서 만들어 준 것인데 처음의 높이와 끝 부분의 높이를 맞춰주는 것으로 큰 의미는 없다.

 

height 값에 10을 넣으면 위와 같은 식이 나옴

그러면 직접 정의한 함수 f(x)를 살펴보자. height가 10일때 x(시간)에 따른 그래프는 위와 같이 나온다.

함수 내 변수 x는 lerp함수를 거치기 떄문에 무조건 0에서 1까지만 들어가도록 되어 있어서 x가 0.5일때는 무조건 고점 height값을 가지도록 되어있다.

즉 이 수식은 포물선 이동에 대한 물리 함수라기보다는 x이동 따로(직선운동), y 이동은 이차곡선 형태로 이동하도록 된 식이다.

 

3.3 떨어지는 방향 보도록 하기

떨어지는 방향 보는거 코드 짜주기

 

4. Rigidbody 방식으로 포물선 운동 구현

다음은 유니티 물리 엔진을 직접 이용해서 구현하는 방식에 대해서 알아보자.

사용하기 쉽고 직관적이지만 너무 애용하다보면 복잡한 구현이 필요할수록 점차 나락으로 빠질것이다.(나처럼)

 

장점 : 이동 단위(속도)가 큰 경우에도 충돌 판정이 정상적으로 이뤄짐(단 TriggerEnter는 속도가 말도안되게 너무 빠르면 정상적으로 작동하지 않을 수 있음)

오른쪽을 보면 물체의 이동속도가 벽의 두께보다 훨씬 높은데도 정상적으로 못넘어가게 막아주고 있다.

 

단점 : 유니티 엔진이 제공하는 것 이상의 기능을 구현할때 힘들어짐.(이 부분은 직접 경험해봐야 안다.)

 

 

4.1 포물선 운동 물리 공식 이해 

인터넷에 쳐보면 바로 나오는 공식이지만 설명이 친절하지는 않다.

한번 내가 포물선 운동 물리 공식에 대하여 설명해보도록 하겠다.(내가 친절하게 설명해준다고는 안함)

 

그 전에 이해해야하는 개념이 몇 가지 있다. 몰라도 되긴하는데 궁금하면 읽어보자.

 

등속 운동과 가속운동

등속 운동은 말 그대로 속도가 일정한 운동을 의미한다.

총을 초속 10m/s로 쐈다.

해당 총알은 10m/s의 등속 운동을 하게 된다.(공기저항 제외)

t초 뒤 총알의 이동 거리는 10m * t이다.

 

등가속 운동은 일정하게 속도가 증가하는 운동을 의미한다. 짱짱한 자동차가 있다고 했을때 풀악셀을 밟아서 초당 10m/s의 속도로 증가하는 운동을 하는 경우가 그에 해당한다.

해당 자동차의 t초 뒤 속도는 10 * t이다.

그리고 자동차의 t초 뒤 이동 거리는 5t^2 이다.(해당 공식을 유도하는 방법은 정적분을 참고하자)

포물선 운동의 이동거리 공식을 보면 식을 이해하려고 하지말고 따라 붙는 변수의 형태만 확인해보자.

x축 이동은 등속운동 y축 이동은 등가속 운동을 한다는 것이다. 포물선 운동에 대해서 조금 더 이해가 되지않는가? x축 운동은 그냥 평범한 이동인것이다.

y축은 계속해서 중력만큼의 힘이 더해져서 아래로 떨어지는 등가속운동을 하는 것이다.

 

포물선 운동 공식 이해

그렇다면 대망의 포물선 운동 공식을 이해해보자.

중력이 작용하는 세계에서 x와, y축 방향 성분을 가지고 있는 v라는 힘을 주게 되면 아래와 같이 설명할 수 있다.

 

각 축에 대한 속도식은 아래와 같다. V의 벡터분해에 대한 것은 따로 찾아보자

여기서 t에 대한 값을 넣으면 그 시간대에 해당하는 각축별 속도를 의미한다.

x축은 어떤 시간값을 넣더라도 항상 동일한 값을 나타내고 y축은 시간이 값이 작아진다.

 

그리고 이동 거리에 대한 정적분 결과는 아래와 같다.

 

5개의 변수 그리고 2개의 식

포물선 운동 설명

포물선 운동 공식에는 2개의 식과 5개의 변수가 나온다.

V, 세타, t, x위치, y위치

우리는 x위치, y위치를 알고있다.

변수는 3개인데 식은 2개다. 따라서 세 변수중 하나를 결정해주면 나머지 2개의 변수가 스스로 결정된다.

세타를 정해주면 속도와 시간이 정해지고

속도를 정해주면 각도와 시간이 정해지고

시간을 정하면 속도와 세타가 정해진다.

 

그에 따라 생기는 문제 원하는 투사체 발사를 못만든다.

하지만 중력을 변수로 바꿔버리고 세타, t를 지정해주면? V와 중력에 대한 값이 연립해서 나오게 된다.

 

이하 작성하다가 말음 ... ( 아마 쭈욱 작성 안될 가능성 높음 )

 

4.2 도착지점 알고 발사 각도 알 때

인터넷에 가장 많이 나와있는 유형

4.3 도착 시간 알고 각도 알 때 

 

4.4 Rigidbody 방식의 한계 - 중력이 정해져 있다 

일단 그 전에 3차원 포물선 운동을 이해하기 쉽게 쉬운 운동으로 변환해서 설명하겠다. 여기서 말하는 3차원은 유니티라고 가정하겠다.

3차원(x y z 좌표평면) 포물선 운동 -> 2차원(x y좌표평면) x축 운동 + 2차원 y축 운동

3차원 운동 예시 : new Vector3 (10, 10, 0) -> 2차원 운동 : new Vector2(10,0) + new Vector2(0, 10) 이렇게 쪼개진다.

 

그렇다면 포물선 운동 공식에 대해서 얘기하기 전에 직선 운동에 대해서 먼저 얘기해보자

물리에서는 -> 직선운동 설명

 

포물선 운동 설명

포물선 운동 공식에는 2개의 식과 5개의 변수가 나온다.

V, 세타, t, x위치, y위치

우리는 x위치, y위치를 알고있다.

변수는 3개인데 식은 2개다. 따라서 세 변수중 하나를 결정해주면 나머지 2개의 변수가 스스로 결정된다.

세타를 정해주면 속도와 시간이 정해지고

속도를 정해주면 각도와 시간이 정해지고

시간을 정하면 속도와 세타가 정해진다.

 

그에 따라 생기는 문제 원하는 투사체 발사를 못만든다.

하지만 중력을 변수로 바꿔버리고 세타, t를 지정해주면? V와 중력에 대한 값이 연립해서 나오게 된다.

 

4.5 중력가속도를 바꿔서 투사체마다 발사 속도와 각도를 정해주기

 

4.6 떨어지는 방향 보도록 하기

 

5. 결론과 요약 

물리 기반 게임이 아닌 이상 그냥 4.2번 방식으로 가는 게 좋다 
짬밥 높은 개발자가 결국 코어 물리로 가게 되면 이해하기 힘든 영역(drag)이 추가되면 그때부터 나락으로 빠지기 시작함

반응형

'Unity' 카테고리의 다른 글

유니티 블루스택 구동  (1) 2020.09.27
유니티 파이어베이스 이벤트 로깅  (0) 2020.09.22
유니티 파이어베이스 로그 비활성화  (2) 2020.02.05
유니티 꿀팁  (0) 2019.02.27
유니티 물체 따라다니도록 하기  (0) 2019.02.24
반응형

1. 개요

2. 프로젝트 요약

3. 프로젝트 가동 영상

4. 프로젝트 결과

 

 

 

 

 

1. 개요

 

위 영상을 본사람들은 이해가 더 빠르다. 안봤다면 한번 보고오자 꽤 재미있는 실험이다.

내가 할 얘기는 나도 저 사람들에게 감명을 받아서 6개월에 걸쳐 Goose라 부르는 프로젝트를 Ameba라는 프로젝트로 똑같이 만들어봤다.

Goose 프로젝트는 슬롯머신이라면 나는 솔리테어로 프로젝트를 진행했다.

 

2. 프로젝트 요약

핵심 기능은 다음과 같다.

 

애드몹 광고 프로젝트 생성

애드몹 배너 광고, IS 광고, RV 광고 생성

구글 트렌드, 인게임 테마 이미지 다운로드

게임에 사용될 리소스 제작

유니티 빌드

플레이스토어 프로젝트 생성 및 리소스 등록

 

위의 핵심 기능을 전부다 관리하고 처리해주는 프로그램을 만든 것이다.

참으로 우여곡절이 많았고 나의 크롤링, 자동화 실력을 더욱 향상 시켜주었다.

이제는 그 어떤 자동화 프로그램도 만들 수 있을 것 같다.

 

3. 프로젝트 가동 영상

2번에서 말했던 핵심 기능을 구동하는 영상을 찍었다.

 

4. 프로젝트 결과

여러분한테 제일 흥미로운건 결과 아니겠는가

 

실제로 플레이하는 사람들은 꽤나 있고 광고도 시청해준다.

프로젝트 초기 단계에서는 올린 게임이 노출되지도 않았고 아무 의미 없는 프로젝트인 줄 알았다.

하지만 2~3달정도 가만히 두니까 사람들이 점차 플레이하더니 유저수가 하나둘씩 늘어났다.

 

반면에 총 7개의 플레이스토어 계정중 5개의 계정이 정지당했으며 정지당한 직접적인 원인을 아직 잘 모르겠다.

 

계정이 정지당하는 바람에 마음편히 가동할 수 있는 프로젝트는 아니라서 결과가 성공적인 프로젝트는 아니었던 것 같다.

반응형
반응형

어떤 상황에서 발생하는지는 모르지만 갑자기 위 에러가 발생하면서 유니티가 꺼진다.

프로젝트 경로/Library/metadata 폴더를 삭제하고 재시작하면 해결된다.

 

아래 페이지 참고했음.

answers.unity.com/questions/1117177/the-file-memorystream-is-corrupted-remove-it-and-l.html

 

 

반응형
반응형

유니티 트레일에는 2개의 Scaling Mode가 있다.

 

Transform과 Rigidbody이다.

 

Transform

Transform은 트레일이 붙어있는 오브젝트가 translate로 움직일 때 트레일이 발생한다.

 

Rigidbody

Rigidbody는 트레일이 붙어있는 오브젝트가 rigidbody(물리)를 force나 velocity를 조절해서 움직이는 경우 트레일이 발생한다.

 

당신이 트레일이 달려있는 오브젝트를 translate로 움직여놓고 ScalingMode가 Rigidbody 거나 그 반대 상황의 경우 트레일이 나타나지 않는다.

 

Scaling Mode는 아래 이미지 부분에서 수정 가능하다.

반응형
반응형

유니티 에디터에서 분명 사운드를 출력했는데 소리를 출력하기까지 조금의 딜레이가 생기는 경우가 있다.

 

구글에 쳐보면 다양한 원인을 말해주는데 그중에 해답은 없었다.

 

하루정도 삽질하다가 회사 동료분이 해답을 알려주셨다.

 

원인은 블루투스 이어폰으로 소리를 들어서 생긴 문제였다.

유선 이어폰이나 블루투스 이어폰을 끄고 디바이스로 소리를 들어보면 딜레이가 발생하지 않았다.

 

정말 써놓고도 이상한 트러블슈팅이지만 누군가는 나와 똑같은 삽질을 할 것 같다.(사실 이전 프로젝트 진행하면서 겪었는데 이번에 또 겪음 빡대가리임)

반응형
반응형

1. 개요

2. 파이어베이스 로깅 방법

3. 파라미터 데이터가 안 쌓이는 경우 

 

 

 

 

 

 

 

 

 

1. 개요

파이어베이스의 기능 중 하나인 Analytics 중에서 이벤트 남기는 방법과 이벤트 파라미터가 쌓이지 않는 문제를 겪어서 기록하고자 글을 쓴다.

 

유니티 파이어베이스 애널리틱스 DOCS

유니티 파이어베이스 SDK 다운로드

 

설치하는 방법에 대해서는 너무 쉬워서 따로 기재하지 않겠다.

다만 기존 SDK의 버전과 동일한 버전을 설치하는 것에 유의하자.

 

회사에서는 이런식으로 이벤트에 대한 목록을 짜주면 그에 맞는 이름과 파라미터를 개발자인 내가 알맞게 쏴주는 형식으로 협업한다.

 

2. 파이어베이스 로깅 방법

공식 Docs에는 이렇게 나와있는데 저 코드만으로는 실제 개발에서 사용하기 까다롭다.

아래 코드로 이벤트를 쉽게 날리도록 하자

 

 public void SendFirebaseEvent(string _eventName, params string[] _params)
    {
        Parameter[] parameters = new Parameter[_params.Length];
        for (var i = 0; i < _params.Length; i++) 
            parameters[i] = new Parameter($"param{i + 1}", _params[i]);
        FirebaseAnalytics.LogEvent(_eventName, parameters);
    }

 

위 함수는 이런식으로 호출하면 된다.

SendFirebaseEvent("이벤트 이름", "첫번째 파라미터", "두번째 파라미터", "세번째 파라미터", ...);

 

찍히는 이벤트에 대한 파라미터의 이름은 무조건 param1, param2,... 이런 식으로 찍히니까 유의하자.

나는 굳이 파라미터에 대한 이름을 정하지 않아도 되는데 파라미터 이름까지 정해주면 좋을 것 같긴 하다.

딕셔너리를 이용해서 커스터마이징 해보세요

 

 

4. 파라미터 데이터가 안 쌓이는 경우 

한 가지 치명적인 실수를 하고 있었는데 파이어 베이스의 이벤트는 쌓이지만 파라미터 데이터가 제대로 쌓이지 않는 문제가 발생했다.

 

로그를 보니 아래와 같이 로그캣이 울부짖고 있었다.

Name must start with a letter. Type, name : evvent param, 1

 

파라미터에 대한 변수 이름을 숫자로 지정했더니 발생한 문제였다.

파라미터의 이름의 첫 글자는 문자열로 정하도록 하자(언더바도 작동 안 함)

반응형
반응형

ejs를 설치했는데도 안되는 사람에게 해당되는 글이다.

 

정상적으로 npm install ejs를 했고

app.set('view engine', 'ejs')도 했는데

router단에서 res.render시 아래 오류가 발생한다.

 

Error: Cannot find module 'ejs'
Require stack:
- C:\Users\user\Desktop\workspace\node_modules\express\lib\view.js
- C:\Users\user\Desktop\workspace\node_modules\express\lib\application.js
- C:\Users\user\Desktop\workspace\node_modules\express\lib\express.js
- C:\Users\user\Desktop\workspace\node_modules\express\index.js
- C:\Users\user\Desktop\workspace\ForkCraneServer\app.js
   at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)
   at Function.Module._load (internal/modules/cjs/loader.js:862:27)
   at Module.require (internal/modules/cjs/loader.js:1042:19)
   at require (internal/modules/cjs/helpers.js:77:18)
   at new View (C:\Users\user\Desktop\workspace\node_modules\express\lib\view.js:81:14)
   at Function.render (C:\Users\user\Desktop\workspace\node_modules\express\lib\application.js:570:12)
   at ServerResponse.render (C:\Users\user\Desktop\workspace\node_modules\express\lib\response.js:1012:7)
   at C:\Users\user\Desktop\workspace\ForkCraneServer\app.js:39:9
   at Layer.handle [as handle_request] (C:\Users\user\Desktop\workspace\node_modules\express\lib\router\layer.js:95:5)
   at next (C:\Users\user\Desktop\workspace\node_modules\express\lib\router\route.js:137:13)

 

아래 오류를 자세히 보면 알겠지만 현재 내 프로젝트 경로가 제대로 지정되지 않았다.

따라서 프로젝트 경로를 지정해줘야한다.

 

아래 코드를 통해서 ejs 모듈의 참조 경로를 지정해주자.

app.engine('ejs', require('ejs').__express)

반응형
반응형

1. 오류

플레이스토어에 APK를 올렸을 때 위와 같은 오류가 발생하면 유니티의 Target API를 보다 높게 변경해야 한다.

본인은 Target API를 28로 지정하였고 플레이스토어에 등록하기 위해서 29 이상으로 변경해서 다시 빌드해야 한다.

 

2. 원인

Edit > Project Settigns > Other Settings에 현재 빌드 타겟 API에 대한 정보가 나와있다. 기본값은 Automatic으로 가장 높은 API를 타겟으로 하는데 28까지만 설치되어있어서 문제가 생긴 것이다.

 

따라서 현재 내 PC에 API Level 29 이상을 설치해야 한다.

 

 

3. 해결방법

인터넷에는 직접 다운받아서 넣거나 다양한 방법이 나와있는데 플랫폼에 상관없이 간편하게 해결할 수 있는 방법을 알려주겠다.

 

유니티 에디터의 SDK 경로 안의 tools/bin으로 이동해야 한다.

모르겠다면 유니티 > Preferences > Android SDK Tools Installed with Unity의 경로에 가보자

 

위와 같이 파일이 있다.(OS에 따라 확장자 상이)

우리는 저 파일 중 sdkmanager를 이용해서 상위 API를 설치해야 한다.

 

cmd를 켜서 해당 파일에 접근하고 sdkmanager.bat --list 를 쳐보자

 

그러면 위쪽에 무수히 많은 설치 가능한 SDK와 현재 설치된 SDK를 보여준다.

 

우리가 필요로 하는 것은 저 녀석들이다. platforms;android-29, platforms;android-30

 

설치방법은 간단하다.

 

sdkmanager.bat "설치하고자 하는 sdk 이름"

 

그러면 원래 28까지밖에 없던 SDK에 30이 새로 생긴다.

 

이후 유니티를 재시작해서 다시 Target API를 확인해보면 새로운 API Level이 생겼다.

반응형