화면 사이즈에 따라 이미지가 보이고 안 보이고 할때
-z축이 0이 아님
'Unity' 카테고리의 다른 글
유니티 함수 연동 안될때 (0) | 2020.08.03 |
---|---|
유니티 로그캣 (0) | 2020.06.29 |
스파인 사용법 (0) | 2020.06.25 |
화면 사이즈에 따라 이미지가 보이고 안 보이고 할때
-z축이 0이 아님
유니티 함수 연동 안될때 (0) | 2020.08.03 |
---|---|
유니티 로그캣 (0) | 2020.06.29 |
스파인 사용법 (0) | 2020.06.25 |
응가 싸는 패턴이다
싱글톤은 유용하지만 유니티에서 지원이 빈약하다
써야한다면 static final로 한번만 생성되게 막자
OnGUI (0) | 2020.07.27 |
---|---|
유니티 버그, 에러, 오류모음 (0) | 2020.07.20 |
자주 쓰는 유니티 코드 모음 (0) | 2020.07.09 |
2019.4.0f1버전의 유니티의
안드로이드 update에서 Time.deltaTime이 제대로 안 먹힐때가 있다.
float Timetime_previous = 0;
void Update()
{
Debug.Log(Time.time - Timetime_previous);
Timetime_previous = Time.time;
}
이걸로 해결 가능하다.
후일담)
2019.4.31f1에서도 동일한 증상이 있고
첫프레임에서 발생하는거 보니 델타타임으로 중요루틴 굴리면 안 될듯
------------------------------------------------------------------------------
Image 컴포넌트를 인풋으로 받을수 없을때
public Image img_comp;
이렇게 쳐도 안되면
using UnityEngine.UIElements로 되어있기 때문
using UnityEngine.UI가 맞음
------------------------------------------------------------------------------
GetCharacterInfo의 characterInfo.advance를 못 받아오는 문제
콜백을 걸어서 사용해야 한다
void Start()
{
Font.textureRebuilt += GetTextWidth;
}
void GetTextWidth(Font font)
{
CharacterInfo characterInfo;
char c = 'a';
if (font.GetCharacterInfo(c, out characterInfo, font.fontSize, FontStyle.Normal))
{
Debug.Log($"c: {c}, characterInfo.advance: {characterInfo.advance}");
Debug.Log($"c: {c}, characterInfo.bearing: {characterInfo.bearing}");
Debug.Log($"GetCharacterInfo Success, textUI.fontSize:{font.fontSize}");
}
else
{
Debug.Log($"GetCharacterInfo Fail, textUI.fontSize:{font.fontSize}");
}
}
이렇게 붙이면 된다. 결국 그래서 별로 쓸모는 없음
------------------------------------------------------------------------------
UGUI 월드스페이스에서 동작 안할경우
------------------------------------------------------------------------------
unrecognized identifier 'UNITY_FOG_COORDS'
상단에
#include "Lighting.cginc"
를 넣어주면 된다
------------------------------------------------------------------------------
CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.
키스토어가 바뀌어버린것이거나 Bundle Version Code가 더 낮은걸 올려버림
------------------------------------------------------------------------------
안드로이드에서만 30프레임으로 고정될때
매낮으로 설정됨
둘중하나를 선택
------------------------------------------------------------------------------
에셋번들로 빌드시 3D모델일부(스킨드 메쉬 렌더러)가 보이지 않는 현상
3D모델들을 Resources폴더 하위에 넣으면 된다
------------------------------------------------------------------------------
에셋번들로 빌드시 믹서가 크래시 나는 현상
믹서들을 Resources폴더 하위에 넣으면 된다
------------------------------------------------------------------------------
빌드시 동영상이 보이지 않을경우
동영상을 Resources폴더 하위에 넣으면 된다
------------------------------------------------------------------------------
안드로이드 이미지 로드시 튕길경우
jpg로 넣어라
png는 TextureFormat.ETC2_RGBA8Crunched 포맷만 되었던가 이것만 안되었던가 둘중하나인데
이걸 구분하기 힘드니까 jpg써라
------------------------------------------------------------------------------
애니메이션이 초기화가 안 되고 자꾸 덧씌우기로 동작할경우
체크해라
------------------------------------------------------------------------------
압축풀때 java.lang.IllegalArgumentExcetion 뜨면서 안될때
파일명들에 한글이랑 - , ` 제거하고 영어랑 띄어쓰기만 써라
------------------------------------------------------------------------------
애니메이션에 마테리얼 프로퍼티값을 등록할수 없을때
Image같은 UI컴포넌트는 원래 안 되고, 메쉬렌더러같이 렌더러계열만 가능
------------------------------------------------------------------------------
2019.4.1f1에서 에셋번들로 실행시 AudioSouce의 PlayDelayed (float)함수가 버튼으로 실행을 넘겨받을경우 작동이 안됨
------------------------------------------------------------------------------
ArgumentException: Mesh can not have more than 65000 vertices
UnityEngine.UI.VertexHelper.FillMesh (UnityEngine.Mesh mesh) (at
아웃라인 컴포넌트 오류이다
텍스트 컴포넌트에 달았는데 텍스트가 너무 길면 발생한다
------------------------------------------------------------------------------
iOS에서 플러그인 익스포트가 안 될때
DirectoryNotFoundException: Could not find a part of the path
"C:/unity/Test/Assets/Plugins/iOS/Helloworld.swift"
or "//DESKTOP-0000/Xcode/Test\Libraries\Plugins\iOS\Helloworld.swift"
폴더경로가 이상해서 그렇다.
네트워크 드라이브나 한글경로 쓰지말고 자신의 드라이브의 영어경로를 쓰자
------------------------------------------------------------------------------
<unknown>:0: error: no such file or directory:
'/Volumes/Xcode/Test/Libraries/Plugins/iOS/Helloworld.swift'
Command
/Users/Test/Desktop/Xcode.app/Contents/Developer/Toolchains
/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
위와 같은 문제다
내부경로 영어경로를 쓰자
------------------------------------------------------------------------------
유니티 zip가 IOS에서 빌드 안될때
넣으삼
------------------------------------------------------------------------------
app transport security has blocked a cleartext http (http //) resource load since it is insecure
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
추가한다.
추가해도 안된다면 Security에 잡다한게 들어가서 그럼
------------------------------------------------------------------------------
렌더카메라가 메인카메라로 잡힐때
태그달아라
------------------------------------------------------------------------------
2019.4.1f1버전의 유니티에서 iOS빌드시 리플렉션 해상도가 다르게 바뀜
------------------------------------------------------------------------------
Found plugins with same names, and . Delete the one of the duplicate plugins.UnityEditor.AndroidPluginImporterExtension:CheckFileCollisions(String)UnityEditorInternal.PluginsHelper:CheckFileCollisions(BuildTarget)UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
2018에서 2019로 올릴때 발생한다
라이브러리 폴더 지우면 폴더가 재구축 되면서 해결된다
------------------------------------------------------------------------------
SerializedObject target has been destroyed.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
특정 인스펙터를 열어둔상태에서 재생하면 발생한다. 다른곳으로 인스펙터를 열면 된다
------------------------------------------------------------------------------
2019.4.1.f1의 particle system force field가 android, ios에서 실행 안됨
에셋번들로 로드할때 실행이 안 되는 현상이 발생하고
레이어를 동일하게 맞춰주고 풀빌드 하면 잘됨
------------------------------------------------------------------------------
unrecognized identifier 'SHADOW_COORDS'
아래 코드를 넣는다
#pragma multi_compile_fwdbase
#include "AutoLight.cginc"
------------------------------------------------------------------------------
씬 이동후 캔버스 먹통되는 현상
이동할때 같이 EventSystem을 이동시켜주거나
이동한 씬에도 EventSystem을 달아준다
평소에는 자동할당 되어서 눈치채기 힘든부분이다
------------------------------------------------------------------------------
AssetBundle(에셋번들)에서 Polygon Collider 2D 미동작
AssetBundle(에셋번들)에서 Particle System Force Field 미동작
체크 해제한다.
동적 메쉬 데이터는 에셋번들에서 제외되기 때문IL2CPP에서만 그런듯?
단점은 불필요한 파일들의 필터링이 안 되기 때문에 빌드시간과 용량이 늘어난다
다행히 스크립트만 포함시키는듯하다
차라리 번들로더랑 같이 해당씬을 포함시키던지 해당기능을 쓰지 않거나 link.xml을 작성하여 Asset폴더에 넣자
참조 : https://docs.unity3d.com/kr/2018.4/Manual/ManagedCodeStripping.html
------------------------------------------------------------------------------
RenderTexture.Create: Depth|ShadowMap RenderTexture
requested without a depth buffer. Changing to a 16 bit depth buffer.
2019.4.1f1에서 렌더텍스처의 DepthTexture를 쓰려고 하면 발생한다
정확히는 Camera의 RenderTexture의 Color Format의 DEPTH_AUTO를 줄때
Depth Buffer가 16bit가 아닐때 발생한다고 하는데 걍 계속 생김
해결방법은 해당 카메라를 쓸때만 키자
------------------------------------------------------------------------------
Attempting to bind Texture ID 125 as UAV, the texture wasn't created with the UAV usage flag set!
enableRandomWrite가 설정된 렌더텍스처만 가능하다
enableRandomWrite는 동적으로 생성시에만 설정 가능하며
만일 기존 렌더텍스처에 할당하려고 하면 RenderTexture.Create failed: format unsupported for random writes - RGBA4 (142).
라는 새로운 오류를 발생시킨다
------------------------------------------------------------------------------
Not allowed to access vertices on mesh '메쉬이름'
Read/Write 체크
------------------------------------------------------------------------------
java.lang.securityexception permission denied (missing internet permission )
------------------------------------------------------------------------------
java.io.IOException: Cleartext HTTP traffic to 링크 not permitted
해당 링크가 https가 아니라서 발생하는 문제이다
예외속성에 해당링크를 추가하는 방법도 있긴한데 ios 지원할거라면 걍 https쓰자
------------------------------------------------------------------------------
Failed running C:\Program Files\Unity\Hub\Editor\2019.4.1f1\Editor\Data\il2cpp/build/deploy/net471/il2cpp.exe
stdout:
Building libil2cpp.so with AndroidToolChain
Output directory: C:\unity\GameName\Temp\StagingArea\assets\bin\Data\Native\arm64-v8a
Cache directory: C:\unity\GameName\Library\il2cpp_android_arm64-v8a\il2cpp_cache
빌드중에 크래시 나면 빌드불가에 빠지는 버그이다
프로젝트 폴더의 Library 폴더아래의
il2cpp_android_arm64-v8a폴더와
il2cpp_android_armeabi-v7a폴더를 지워주면 된다
------------------------------------------------------------------------------
iOS framework addition failed due to a CocoaPods installation failure. This will will likely result in an non-functional Xcode project.
------------------------------------------------------------------------------
1. undefined symbol _objc_class_$_
2. _objc_class_$_firtransactionresult
3. unity _OBJC_CLASS_$_ GKLocalPlayer
4. 'FBSDKShareKit/FBSDKShareKit.h' file not found
5. ios framework addition failed due to a cocoapods installation failure
위 5개 전부 동일한 원인의 버그이다
얼핏보면 코코아포드 손상이나 GameKit.framework 미설치로 보이겠지만 전혀 아니다
유니티 서비스 인증 만료로 생긴 버그이다. 해결방법은 하단 이미지 참조
알고보니 하단설정이다
------------------------------------------------------------------------------
cocoapods installation detected /usr/local/bin/pod
이미 설치되어 있다는 소리이다
지우고 싶다면 터미널에서 sudo gem uninstall cocoapods를 친다
------------------------------------------------------------------------------
error CS0234: The type or namespace name 'Graphics' does not exist in the namespace 'System.Drawing' (are you missing an assembly reference?)
dll을 넣어도 문제가 생긴다면 System.Drawing 중복으로 인한 참조 오류이다
4.0으로 올리고 dll을 넣으면 된다
------------------------------------------------------------------------------
Signing for "Unity-iPhone" requires a development team.
Select a development team in the Signing & Capabilities editor that matches the selected profile "키".
인증서 기간 조금 남았어도 뜨는듯
------------------------------------------------------------------------------
UnityPlayerActivity.java uses or overrides a deprecated API.
UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()
안드로이드 Minimum API레벨이 너무 낮아서 그렇다
30으로 올려주자
------------------------------------------------------------------------------
Cycle in dependencies between targets 'Unity-iPhone' and 'UnityFramework'; building could produce unreliable results.
빌드할때 뭔가 빨간줄 뜨면서 헤더가 빠진채 빌드가 되었을것이다
빨간줄 안뜨게 수정하면 된다
------------------------------------------------------------------------------
Image UGUI에서 마테리얼값 바꿀때
https://answers.unity.com/questions/920091/how-can-i-change-the-shader-parameters-for-an-ui-i.html
Material mat = Instantiate(image.material);
mat.SetFloat("_SomeProperty", 1f);
image.material = mat;
이거쓰면 전역 건드리는 문제 해결된다
------------------------------------------------------------------------------
블루투스 권한 못 받아올때
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
이걸 Plugins/Android/AndroidManifest.xml에 넣어준다
위치는 이런식으로</application>와 </manifest>사이에 넣어야 한다
---------------------------------------------------------------------------------
Note: \Temp\gradleOut\unityLibrary\src\main\java\com\unity3d\player\UnityPlayerActivity.java uses or overrides a deprecated API.
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
api 올려주면 된다 24쯤?
올려도 발생할때 있는데 타겟api가 낮은 경우로 블루투스의 경우 31을 깔아주면 된다
---------------------------------------------------------------------------------
Duplicated input semantics can't change type, size, or layout ('TEXCOORD1'). at line 82 (on d3d11)
이 문제인데 보다시피 설명과 달리 TEXCOORD1는 한번밖에 쓰여있지 않다
이유는 UNITY_FOG_COORDS에서 TEXCOORD1을 쓰기 때문
TEXCOORD2로 수정해주면 해결된다
---------------------------------------------------------------------------------
ArgumentException: The Assembly Mono.WebBrowser is referenced by System.Windows.Forms
---------------------------------------------------------------------------------
Not a WAVE file - no RIFF header
NAudio의 오류
파일명의 확장자에 .wav가 안 붙어있어서 발생함
---------------------------------------------------------------------------------
CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.
C:/Program Files/Unity/Hub/Editor/2019.4.1f1/Editor/Data/PlaybackEngines/AndroidPlayer\SDK\platform-tools\adb.exe -s "RF9NC0529JN" install -r -d "D:\~~~.apk"
stderr[
adb: failed to install D:\~~.apk: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl1319470982.tmp/base.apk (at Binary XML file line #40): com.unity3d.player.UnityPlayerActivity: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present]
]
stdout[
]
exit code: 1
Target API Level이 Automatic이면 가끔씩 잘 못 잡아서 그럼
수동으로 할당
---------------------------------------------------------------------------------
Microsoft (R) Visual C# Compiler version 2.9.1.65535 (9d34608e) Copyright (C) Microsoft Corporation. All rights reserved
특정 컴퓨터에서 포톤을 열려고 하면 이렇게 된다
2019.4.1f1에서 발생했고 2019.4.31f1으로 올리면 해결된다
---------------------------------------------------------------------------------
File couldn't be read! UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
위 버그랑 동일한 문제다
해결법도 같다
---------------------------------------------------------------------------------
The referenced script on this Behaviour
미싱컴포넌트 있어서 그렇다
지워
---------------------------------------------------------------------------------
Unsupported type BitField
UnityEditor.EditorApplication:Internal_CallUpdateFunctions ()
32비트까지만 지원해서 안된다느니 어쩌구~
결론은
보통 레이어마스크를 인자로 받다가 프리팹에서 꼬여서 발생한다
public LayerMask layerMask = -1;
이 부분이 문제인데 그냥은 안 생긴다
원래 int형으로 만들고 저장한 후에 나중에 LayerMask로 바꾼 괴랄한 경우에 생긴다
해당 컴포넌트를 Revert해서 기록된 쓰레기 데이터를 날려주면 된다
---------------------------------------------------------------------------------
래그돌(Ragdoll)에 AddExplosionForce가 안먹히는 현상
GetComponent<Rigidbody>() 써서 그렇다.
콜라이더는 회전문제때문에 보통 오브젝트가 분리되어 있으니까..
attachedRigidbody로 수정해주자
//var rigidbody = collider.GetComponent<Rigidbody>();
var rigidbody = collider.attachedRigidbody;
if (rigidbody)
{
rigidbody.AddExplosionForce(explosionForce, explosionCenter, radius);
}
---------------------------------------------------------------------------------
2019.4.31f1에서
hit.transform.name에 이상한게 뜨는 현상
내부적으로 hit.rigidbody.transform.name을 쓰기 때문이다 (이뭐병...)
반드시 hit.collider.transform.name을 쓰자
---------------------------------------------------------------------------------
2019.4.1f1에서 발생
Missing Project ID
걍 계정 두개 쓰다가 다른 계정으로 열어서 걸림
즉 권한부족
일단 아래사진대로 눌러보면
이렇게 뜰것이다
https://dashboard.unity3d.com/
먼저 유니티 대시보드 들어가서
계정을 초대하고 권한을 설정해준다
나는 부계정이라서 매니저 권한 줬는데 보통은 게스트나 유저를 주면 될것이다
그리고 유니티에서 리프레시를 누르면
짜잔 액세스 성공
내가 특이케이스라 그렇지 일반적인 경우라면 다른 직원이 초대를 못받은 경우겠다
끝
---------------------------------------------------------------------------------
Target Android SDK not installed
혹은
UnityException: Target Android SDK not installed
Android SDK does not include your Target SDK of 30.
SDK를 순차적으로 설치하지 않은 상태에서 없는 SDK를 요청하면 뜬다
이게 무슨 소리나면 내가 원래 34버전을 요청해서 업데이트 받았는데
도중에 30이 필요해서 맥시멈을 30으로 내렸더니 업데이트창 없이 바로 이 창이 뜸
해결방법은
이 글의 '중간버전 설치방법' 탭을 확인하자
---------------------------------------------------------------------------------
패키지를 파싱하는 중 문제가 발생했습니다
영어로는 There was a problem while parsing the package라고 한다
https://discussions.unity.com/t/problem-parsing-package-with-api-level-31/249651
여기서 보면 android:exported="true"인지 머시긴지를 넣으라고만 한다
이렇게 적으면 으뜩케 알아먹으란 건데?
먼저 Plugins/Android/AndroidManifest.xml를 열면 이렇게 적혀있다
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.unity.ads" android:versionName="1.0" android:versionCode="1">
<application>
<uses-library android:required="false" android:name="org.apache.http.legacy" />
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-3940256099942544~3347511713" />
<meta-data android:name="com.google.unity.ads.UNITY_VERSION" android:value="2021.1.10f1" />
</application>
</manifest>
여기에
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
이걸 넣어서 아래처럼 수정했다
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.unity.ads" android:versionName="1.0" android:versionCode="1">
<application>
<uses-library android:required="false" android:name="org.apache.http.legacy" />
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-3940256099942544~3347511713" />
<meta-data android:name="com.google.unity.ads.UNITY_VERSION" android:value="2021.1.10f1" />
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
</manifest>
틀린그림 찾기 알아서 잘 하시길
잘보면 알겠지만 activity에 android:exported="true"를 넣어야 하는데
activity가 없어서 activity를 추가하고 거기에 android:exported="true"를 넣었다
activity는 application안에 들어가야 해서 </application> 바로 위에 써넣었다
그리고 ca-app-pub-3940256099942544~3347511713는 데모키니까 알아서 각자의 키로 수정해야한다
당장 급하다면 API를 낮춰서 빌드하거나 컴퓨터랑 폰 연결후 유니티에서 Build And Run하면 될듯
테스트 하다 말긴 했는데 위에 풀코드 말고
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:exported="true">
</activity>
이렇게 넣어도 부팅은 되긴 했다.
하지만 유니티 버전을 낮게해서 도중에 팅겼었음
---------------------------------------------------------------------------------
Android resource linking failed See the Console for details.
말그대로 오류는 콘솔창을 보고 해결하란 뜻
---------------------------------------------------------------------------------
2019.4.1.f1과 2019.4.31f1에서 발생
> Task :unityLibrary:preBuild UP-TO-DATE
> Task :launcher:preBuild UP-TO-DATE
> Task :unityLibrary:preReleaseBuild UP-TO-DATE
> Task :unityLibrary:GoogleMobileAdsPlugin.androidlib:preBuild UP-TO-DATE
> Task :unityLibrary:GoogleMobileAdsPlugin.androidlib:preReleaseBuild UP-TO-DATE
> Task :unityLibrary:checkReleaseManifest UP-TO-DATE
> Task :launcher:prepareLintJar UP-TO-DATE
애드몹 업뎃하고나니 발생함
저거랑 별개로
Note: \Temp\gradleOut\unityLibrary\src\main\java\com\unity3d\player\UnityPlayerActivity.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
랑
CommandInvokationFailure: Gradle build failed.
도 같이 뜸
찾아보니 커스텀 그래들을 쓰라고 한다
근데 난 이런 해결방식 존나 싫어함
왜?
나중에 또 고쳐야 하니까
생각해보면 걍 유니티가 옛날버전이라 발생하는 문제니까
유니티를 2019.4.1.f1에서 2020.3.48f1으로 올려서 고침
오류코드wmup20230925ASM7과도 관련이 있을수 있으니
또 발생하면 참고바람
---------------------------------------------------------------------------------
A failure occurred while executing
GoogleMobileAds-v8.5.2가 설치된 상태에서 유니티 버전이 2020.3.48f1이 아니라서 발생함
---------------------------------------------------------------------------------
Assembly 'Assets/ExternalDependencyManager/Editor/1.2.177/Google.IOSResolver.dll' will not be loaded due to errors:
Unable to resolve reference 'UnityEditor.iOS.Extensions.Xcode'. Is the assembly missing or incompatible with the current platform?
Reference validation can be disabled in the Plugin Inspector.
GoogleMobileAds-v8.5.2가 설치된 상태에서
유니티를 2019.4.1.f1에서 2022.3.5f1으로 올려서 발생함
IOSResolver 두개를 지워서 고치긴 했는데 원론적인 방법은 아닌듯
그래서 더 찾아봄
https://github.com/googlesamples/unity-jar-resolver/issues/441
여기 보면 2021.1.10에서는 정상 동작한단다.
그래서 찾아보니 이런거도 있었음
보니까 걍 얘내들이 2021.1.10 기준으로 만들어서 생긴 문제다
그래서 2022.3.5f1에서 2021.1.10으로 다운그레이드해서 해결
근데 이거 비안정버전이라 2020.3.48f1으로 더 낮췄다
그리고 해결했단거도 정확히 따지면 재생할때 오류창이 뜨긴 하는데 동작은 한다.(...)
이거 체크하면 재생해도 오류 안 뜬다
---------------------------------------------------------------------------------
오류코드wmup20230925ASM7
java.lang.UnsupportedOperationException: This feature requires ASM7 See the Console for details.
빌드버전코드 올리고 빌드하니 발생함
응?
오류창을 더 보니 이런게 쓰여있다
> Configure project :launcher
WARNING: The option setting 'android.enableR8=false' is deprecated.
It will be removed in version 5.0 of the Android Gradle plugin.
You will no longer be able to disable R8
또 그래들 오류냐?
근데 이게 유니티랑 애드몹 패키지 버전업하면서 사라졌는데
버전수정하면서 그래들이 재갱신 되면서 문제가 발생한듯 하다
여기서 보니까 안드로이드 7.0으로 올리니 문제없단다
그러고보니 원래 미니멈 올리고 테스트 했었는데 그게 잔류했었나보다
API 24로 올리고 해결
---------------------------------------------------------------------------------
유니티 드래그 안 될때
컴퓨터 재부팅 하면 됨
---------------------------------------------------------------------------------
Controller 'Animator Controller': Statemachine for layer 'Base Layer' is missing.
애니메이터를 코드로 생성할때 state가 없어서 발생하는 문제이다
var newState = new AnimatorState();
EditorUtility.CopySerialized(state.state, newState);
원래 이렇게 썼었는데
var newState = new AnimatorState();
CopyClass(state.state, newState);
이렇게 고쳤다
---------------------------------------------------------------------------------
CreateAsset() should not be used to create a file of type '' - consider using AssetDatabase.ImportAsset() to import an existing '' file instead or change the file type to '*.asset'. This error will in a future release be changed to an exception.
AssetDatabase.CreateAsset에서 발생하는 문제이다
AssetDatabase.CreateAsset(asset, path);
근데 난 확장자 다 제대로 넣었는데도 발생했다
알고보니까 확장자만 지정해주고 파일명 공백일때도 발생하더라
파일명 아무거나 넣어서 해결
싱글톤 패턴 (0) | 2020.07.20 |
---|---|
자주 쓰는 유니티 코드 모음 (0) | 2020.07.09 |
사소한 c# 테크닉 (0) | 2020.07.08 |
뭔가 유용한데 정리하기 애매한것들
나중에 정리하자
씬 어딘가에 있는 컴포넌트를 불러옴. 매니저컴포넌트같은걸 다룰때 좋음. 할당 안해도 되니까
부하가 크니 사용시 주의
자주 호출할땐 아래의 '싱글톤에서 최상위 부모를 불러올때' 항목 참고
FindObjectOfType<클래스명>();
FindObjectsOfType을 대체하는 함수
2021.3.18에 추가됨
차이점은 FindObjectsByType은 정렬을 할지 안할지 정할수 있어서 정렬을 안 하면 속도가 더 빠르다는정도
var targets = FindObjectsByType<Renderer>(FindObjectsSortMode.None);
모든 자식들중에 해당 게임오브젝트가 존재하는지 검색함
단 Transform이 달려있어야함
System.Array.Find(transform.GetComponentsInChildren<Transform>(), x => x.name == "게임오브젝트명")
태그검색
GameObject.FindGameObjectsWithTag("태그명");
문자열로 레이어 체크
gameObject.layer == LayerMask.NameToLayer("레이어명")
카메라 레이어 토글
var layerIndex=LayerMask.NameToLayer("레이어명");
camera.cullingMask ^= 1 << layerIndex;
레이어마스크 추가 삭제
//추가
layerMask |= 1 << layer;
//삭제
layerMask &= ~(1 << layer);
컴포넌트 달린 오브젝트 생성
var gameObject = new GameObject(nameof(SampleClass), typeof(SampleClass));
컴포넌트를 활성화 하거나 비활성화할때
GetComponent<Image>().enabled = false;
유니티 에셋 파일 변경시 호출
#if UNITY_EDITOR
클래스명()
{
EditorApplication.projectChanged += GetFileData;
}
void GetFileData()
{
//실행문
}
#endif
프리팹 저장
var target_ClassName = target as ClassName;
if (PrefabUtility.GetPrefabAssetType(target_ClassName.gameObject) != PrefabAssetType.NotAPrefab)
{
PrefabUtility.SavePrefabAsset(target_ClassName.gameObject);
}
텍스트 일부분만 컬러주기, 리치텍스트
Rich Text가 적용되어 있어야 하는데 일반적으론 적용되어있으니 상관없음
텍스트컴포넌트.richText = true;
텍스트컴포넌트.text=
"<color=#ff0000>빨간색</color>
<color=green>초록색</color>
<color=#0000FFc0>반투명파란색</color>
<b>굵게</b>
<i>기울임</i>
<size=50>사이즈50</size>
<material=2>매터리얼2번</material>
"
;
버튼을 누르면 URL실행
if (GUILayout.Button("URL실행"))
{
Application.OpenURL("https://wmmu.tistory.com/");
}
인스펙터의 값을 글로벌로 저장할때 ScriptableObjects를 사용
스크립트테이블오브젝트
using UnityEngine;
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class SpawnManagerScriptableObject : ScriptableObject
{
public string prefabName;
public int numberOfPrefabsToCreate;
public Vector3[] spawnPoints;
}
string.IsNullOrEmpty("문자열")
폴더 이름 반환
var folderPath=AssetDatabase.GetAssetPath(object형폴더);
string[] fileNames = AssetDatabase.GetSubFolders(folderPath);
폴더 아래의 Sprite이름들 반환
{
var folderPath=AssetDatabase.GetAssetPath(object형폴더);
string[] guidFilePathSprites = AssetDatabase.FindAssets($"t:{typeof(Sprite).Name}", new string[] { folderPath });
Sprite[] sprites = new Sprite[guidFilePathSprites.Length];
for (int i = 0; i < sprites.Length; i++)
{
var path=AssetDatabase.GUIDToAssetPath(sprites[i]));//Assets/FileName.Sprite 같은식으로 반환
sprites[i]=AssetDatabase.LoadAssetAtPath<Sprite>(path);
}
}
정적 업데이트
[InitializeOnLoad]
public class MyWindow : EditorWindow
{
static MyWindow()
{
EditorApplication.update -= StaticUpdate;
EditorApplication.update += StaticUpdate;
}
static long lastTime = 0;
public static void StaticUpdate()
{
if ((System.DateTime.Now.Ticks-lastTime)/10000000 >= 3)//3초마다 동작
{
//실행문
lastTime = System.DateTime.Now.Ticks;
}
}
}
Time.time 타이머 예제
가끔 지속체크 해야해서 코루틴 쓰기 곤란한거 쓸때 쓰면 좋음
public Text respawnTimeText;
public Image respawnProgress;
float lastDeathTime = float.MinValue;
/// <summary>
/// update에서 지속 호출
/// </summary>
public void RespawnCheck()
{
var nowTime = Time.time;
var delay = 10;
if (nowTime < lastDeathTime + delay)
{
//부활대기중
var respawnTime = (lastDeathTime + delay) - nowTime;
respawnTimeText.text = respawnTime.ToString("N0"); //10부터 시작
respawnProgress.fillAmount = 1f - respawnTime / delay; //0부터 시작
respawnTimeText.gameObject.SetActive(true);
respawnProgress.gameObject.SetActive(true);
}
else
{
if (lastDeathTime > 0)
{
//리스폰
Respawn();
lastDeathTime = float.MinValue;
}
//생존중
respawnTimeText.gameObject.SetActive(false);
respawnProgress.gameObject.SetActive(false);
}
}
public void Respawn()
{
(var poses, var rot) = GameSystem.GetInstance().GetSpawnPoints(GetComponent<PhotonCharacter>().team);
transform.position = poses[0];
transform.rotation = rot;
GetComponent<PhotonCharacter>().hp = 100;
GetAnimator().GetComponent<DynamicRagdoll>().Deactive();
}
public void Death()
{
lastDeathTime = Time.time;
}
모든 씬에서 단 한번만 자동생성되는 오브젝트
public class GameManager : MonoBehaviour
{
static GameObject gameManager;
static void CreateInstance()
{
if (gameManager == null)
{
DontDestroyOnLoad(new GameObject(nameof(GameManager), typeof(GameManager)));
//nameof가 오브젝트명이고 typeof가 addcomponant
}
}
static GameManager()
{
if(Application.isEditor==false)
{
CreateInstance();
}
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPlaying)
{
CreateInstance();
}
#endif
}
열닫 가능한 코드
#region 주석
#endregion
웹컬러 변환
출력은 #이 빠져나오고 입력은 #이 붙어야 하는 미쿠친구 함수니까 조심하자
string webColor = $"#{ColorUtility.ToHtmlStringRGB(Color.red)}";
//webColor = #FF0000
string webColorRGBA = $"#{ColorUtility.ToHtmlStringRGBA(Color.red)}";
//webColor = #FF0000FF
Color color;
ColorUtility.TryParseHtmlString(webColor, out color);
//color = RGBA(1.000, 0.000, 0.000, 1.000)
에디터 모드에서도 MonoBehaviour를 동작하게 함
update나 start이런 함수도 작동
[ExecuteInEditMode]
데이터 타입 이름 구한거
Debug.Log($"bool: {typeof(bool).Name}"); //Boolean
Debug.Log($"char: {typeof(char).Name}"); //Char
Debug.Log($"string: {typeof(string).Name}"); //String
Debug.Log($"short: {typeof(short).Name}"); //Int16
Debug.Log($"int: {typeof(int).Name}"); //Int32
Debug.Log($"long: {typeof(long).Name}"); //Int64
Debug.Log($"float: {typeof(float).Name}"); //Single
Debug.Log($"double: {typeof(double).Name}"); //Double
배열을 콤마가 붙은 문자열로 반환
string strData = $"({string.Join(",", 배열데이터)})";
string형이 아닌 배열일때
string strData = $"({string.Join(",", Array.ConvertAll(배열데이터, x => x.ToString()))})";
하이어라키의 해당 오브젝트의 자식계층에서 최하위로 설정함, 부모는 변하지 않음
transform.SetAsLastSibling();
리플렉션으로 애니메이션 윈도우 접근
var animationWindowType = System.Type.GetType("UnityEditor.AnimationWindow,UnityEditor");
var animationWindow = Resources.FindObjectsOfTypeAll(animationWindowType)[0];
마우스에 대고있는 윈도우 이름
var mouseOverWindow = EditorWindow.mouseOverWindow;
if (mouseOverWindow != null)
{
Debug.Log("mouseOverWindow: " + mouseOverWindow.GetType().ToString());
}
폰이 스스로 종료되지 않도록
Screen.sleepTimeout = SleepTimeout.NeverSleep; //네버슬립모드
백그라운드에서도 동작함
Application.runInBackground=true;
TextUI의 적절한 가로 사이즈, 캐릭터(문자)의 위치를 구할때 가아아아끔씩 쓴다
GetComponent<Text>().preferredWidth
씬에디터상에 박스를 표시
//에디터상에서 박스위치 표시할때 사용
private void OnDrawGizmos()
{
Gizmos.DrawWireCube(borderCenter, borderSize);
}
public Vector3 borderCenter = Vector3.zero;
public Vector3 borderSize = new Vector3(200,100,200);
배속설정, 디버깅할때 유용하더라
Time.timeScale=2;
싱글톤에서 최상위 부모를 불러올때
v1
static MainSystem mainSystemPrivate;
public static MainSystem mainSystem
{
get
{
if (mainSystemPrivate == null)
{
mainSystemPrivate = FindObjectOfType<MainSystem>();
}
return mainSystemPrivate;
}
}
v2
네이밍만 바뀜
static GameSystem gameSystem = null;
public static GameSystem GetInstance()
{
if (gameSystem == null)
{
gameSystem = FindObjectOfType<GameSystem>();
}
return gameSystem;
}
팝업창을 띄움, 에디터 전용
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
public class Class : MonoBehaviour {
static Class()
{
UnityEditor.EditorUtility.DisplayDialog("제목", "내용", "네", "아니요");
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
#endif
인스턴트 SE
public void InstantiateSE(AudioClip clip)
{
if (clip==null)
{
Debug.Log("clip==null");
return;
}
var gameObject = new GameObject($"SoundEffect({clip.name})");
var audioSource = gameObject.AddComponent<AudioSource>();
audioSource.clip = clip;
audioSource.Play();
Destroy(gameObject, audioSource.clip.length + 3f);
DontDestroyOnLoad (gameObject);
}
유니티 버전
Application.version
Predicate 샘플
public static class Array
{
public static int[] FindIndexAll<T>(T[] array, System.Predicate<T> match)
{
var indexList = new List<int>();
for (int i = 0; i < array.Length; i++)
{
if (match.Invoke(array[i]))
{
indexList.Add(i);
}
}
return indexList.ToArray();
}
}
// Start is called before the first frame update
void Start()
{
var strTest = new string[] { "A", "B", "C", "A", "B" };
var indexes = Array.FindIndexAll(strTest, x => x == "A");
Debug.Log(string.Join(",",indexes)); //0,3을 반환
}
현재 언어가 영어인지
if(Application.systemLanguage == SystemLanguage.English)
인풋필드가 활성화 되어있는지
if((InputField!=null)&& (InputField.isFocused))
{
}
스크린사이즈 변경
private void Awake()
{
if (Debug.isDebugBuild)
{
var hei = 480;
Screen.SetResolution(Screen.width * hei / Screen.height, hei, true);
}
}
fps측정
float fps = 60;
private void OnGUI()
{
fps = Mathf.Lerp(fps, (1 / Time.deltaTime), 0.05f);
GUI.Box(new Rect(100, 0, 200, 24), "FPS: " + (int)fps);
}
스크롤뷰의 콘텐츠 위치를 항상 아래쪽으로 잡을때
scrollRect.verticalScrollbar.value = 0;
이름으로 블렌드 쉐이프 설정
var skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
var blendShapeIndex=skinnedMeshRenderer.sharedMesh.GetBlendShapeIndex("ShapeKeyName");
skinnedMeshRenderer.SetBlendShapeWeight(blendShapeIndex, weight);
마우스 위치 표시
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Debug.DrawLine(ray.origin, hit.point,Color.red);
}
else
{
Debug.DrawLine(ray.origin, ray.origin + ray.direction * 5);
}
자식리스트를 불러옴
//켜진것만
var childList = new List<GameObject>();
for (int i = 0; i < transform.childCount; i++)
{
var child = transform.GetChild(i).gameObject;
if (child.activeInHierarchy)
{
childList.Add(child);
}
}
//전부
var childList = new List<GameObject>();
for (int i = 0; i < transform.childCount; i++)
{
childList.Add(transform.GetChild(i).gameObject);
}
uuid
빌드조건에 따라 쉽게 바뀌니 주의
안드로이드면 키스토어만 바뀌어도 기준값이 바뀌고
애플이면 xcode에서 직접 빌드했는지 아닌지에 따라서도 바뀐다
SystemInfo.deviceUniqueIdentifier
자주쓰는 애니메이션 이벤트
public void InstantiateSE(AudioClip clip)
{
if (clip==null)
{
Debug.Log("clip==null");
return;
}
var gameObject = new GameObject($"SoundEffect({clip.name})");
var audioSource = gameObject.AddComponent<AudioSource>();
audioSource.clip = clip;
audioSource.Play();
Destroy(gameObject, audioSource.clip.length + 3f);
}
scrollRect(Scroll Rect) 스크롤좌표 초기화
scrollRect.horizontalNormalizedPosition = 0f;
scrollRect.verticalNormalizedPosition = 0f;
GPGS토큰
string googleIdToken = null;
string googleAccessToken = null;
if (PlayGamesPlatform.Instance.IsAuthenticated())
{
googleIdToken = PlayGamesPlatform.Instance.GetIdToken();
//googleIdToken = ((PlayGamesLocalUser)Social.localUser).GetIdToken(); 이거도 된다고는 함
googleAccessToken = PlayGamesPlatform.Instance.GetServerAuthCode();
}
else
{
Debug.LogError("GPGS에 연결되어있지않아 토큰을 받아올수 없음");
}
//ID토큰은 공개적인거고 Access토큰은 비공개적인것인듯하다(불확실)
최대값을 지정 해 줌으로서 min값을 구할때 쓸 수 있다
long minScore = long.MaxValue;
게임종료
일반적인 상황에서는 쓸일이 없지만
번들로더같은곳에서 다운로드 취소버튼을 누른다던지 PC용게임을 만들때 사용함
public void Exit()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
Enumerable To List
IEnumerable<DataSnapshot> childrens;
List<DataSnapshot> snapshots= Enumerable.ToList(childrens);
Enumerable To Array
IEnumerable<DataSnapshot> childrens;
DataSnapshot[] snapshots= Enumerable.ToArray(childrens);
레이캐스트2D
유니티4버전이라서 추가 업뎃 해야할듯
RaycastHit2D ray;
Vector3 pos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
ray = Physics2D.CircleCast ((Vector2)pos,0.1f,Vector2.zero);
Debug.DrawRay (mpos,ray.direction,Color.red);
if(ray.transform != null) //빔을 쏴서 존재하는지
{
Debug.Log (ray.point);
Debug.DrawLine(mpos, ray.point, Color.blue);
Debug.Log (ray.transform.GetInstanceID ().ToString());
}
레이캐스트 everything
var everything = ~0;
레이캐스트 샘플
유니티 공식문서 코드에서 조금만 수정했다
주의 : hit.transform은 절대 절대 절대 절대 절대 쓰지말자
float maxDistance = 1000;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out RaycastHit hit, maxDistance >= 0 ? maxDistance : Mathf.Infinity))
{
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);
}
else
{
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * maxDistance, Color.white);
}
레이캐스트 2점쇼바
public class Piston : MonoBehaviour
{
public Transform pistonStart;
public Transform pistonEnd;
void Update()
{
var forward = (pistonEnd.position - pistonStart.position).normalized;
var distance = Vector3.Distance(pistonStart.position, pistonEnd.position);
if (Physics.Raycast(pistonStart.position, forward, out RaycastHit hit, distance,1))
{
transform.position = pistonEnd.position - forward*(distance - hit.distance);
}
else
{
transform.position= pistonEnd.position;
}
}
}
레이캐스트 화면터치
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray))
{
//클릭시 실행
}
레이캐스트 화면기준 발사 3D
//var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var screenCenter = new Vector3(Screen.width / 2, Screen.height / 2, 0);
var ray = Camera.main.ScreenPointToRay(screenCenter);
float maxDistance = 1000;
if (Physics.Raycast(ray, out RaycastHit hit, maxDistance >= 0 ? maxDistance : Mathf.Infinity))
{
Debug.DrawLine(ray.origin, ray.GetPoint(hit.distance), Color.green);
}
else
{
Debug.DrawLine(ray.origin, ray.GetPoint(1000), Color.yellow);
}
디버그 로그 비활성
v1
디버그모드일때만 작동
public class SampleClass : MonoBehaviour
{
static class Debug
{
public static void Log(string log)
{
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.development)
#else
if (Debug.isDebugBuild)
#endif
{
UnityEngine.Debug.Log(log);
}
}
public static void LogError(string log)
{
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.development)
#else
if (Debug.isDebugBuild)
#endif
{
UnityEngine.Debug.LogError(log);
}
}
}
v2
맨 처음에 한번만 적어주면 됨
#if UNITY_EDITOR
if (UnityEditor.EditorUserBuildSettings.development)
#else
if (Debug.isDebugBuild)
#endif
{
Debug.logger.logEnabled=false
}
Define 전역설정
특정 패키지가 임포트 되었을때만 활성화 된다던지가 가능
충돌반사
public float damageSpeed = 3;
public void OnCollisionEnter(Collision collision)
{
if (collision.relativeVelocity.magnitude > damageSpeed)
{
explosionRot = Vector3.Reflect(-collision.relativeVelocity, collision.contacts[0].normal);
explosionPower = collision.relativeVelocity.magnitude * 0.5f;
}
}
충돌반사 네트워킹
https://ahzkwid.booth.pm/items/4471500 에서 사용중이다
public void OnCollisionEnter(Collision collision)
{
//https://ahzkwid.booth.pm/items/4471500
if (GetComponent<VRC_Pickup>() == null)
{
return;
}
if (Networking.IsOwner(gameObject))
{
if (collision.relativeVelocity.magnitude > damageSpeed* DamageSpeedMultiple)
{
explosionRot = Vector3.Reflect(-collision.relativeVelocity, collision.contacts[0].normal);
explosionPower = collision.relativeVelocity.magnitude * 0.5f;
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, nameof(ExplosionEffect));
Delete();
}
}
}
충돌파워에 따른 사운드
void OnCollisionEnter(Collision collision)
{
if (impactSound.isPlaying)
{
return;
}
var volume = collision.relativeVelocity.magnitude;
volume = Mathf.Clamp(volume, 0.1f, 1f);
impactSound.volume = volume;
impactSound.Play();
}
일정시간뒤 자동 삭제
using UnityEngine;
public class DelayDestroy : MonoBehaviour
{
public float delay = 3;
void Start()
{
Destroy(gameObject, delay);
}
}
부위데미지
var partDamage = 1f;
switch (humanBodyBones)
{
case HumanBodyBones.LeftUpperLeg:
case HumanBodyBones.RightUpperLeg:
partDamage = 0.9f;
break;
case HumanBodyBones.LeftLowerLeg:
case HumanBodyBones.RightLowerLeg:
partDamage = 0.7f;
break;
case HumanBodyBones.Spine:
case HumanBodyBones.Chest:
case HumanBodyBones.UpperChest:
case HumanBodyBones.Hips:
partDamage = 1f;
break;
case HumanBodyBones.Neck:
case HumanBodyBones.Head:
partDamage = 2f;
break;
case HumanBodyBones.LeftShoulder:
case HumanBodyBones.RightShoulder:
case HumanBodyBones.LeftUpperArm:
case HumanBodyBones.RightUpperArm:
partDamage = 0.8f;
break;
case HumanBodyBones.LeftLowerArm:
case HumanBodyBones.RightLowerArm:
partDamage = 0.7f;
break;
case HumanBodyBones.LeftHand:
case HumanBodyBones.RightHand:
case HumanBodyBones.LeftFoot:
case HumanBodyBones.RightFoot:
case HumanBodyBones.LeftToes:
case HumanBodyBones.RightToes:
partDamage = 0.5f;
break;
}
Enum1에서 Enum2로 변환
var enum2 = (Enum2)System.Enum.Parse(typeof(Enum2), enum1.ToString());
해당 게임오브젝트의 최상위루트 반환
v1
적용예제 : https://github.com/ahzkwid/AhzkwidAvatarTools
Transform GetRoot(Transform transform)
{
var parents = transform.GetComponentsInParent<Transform>(true);
Transform root = null;
if (parents.Length == 1)
{
root = transform;
}
else
{
root = System.Array.Find(parents, parent => parent.GetComponentsInParent<Transform>(true).Length == 1);
}
return root;
}
근데 내장함수 있었음;;
v2
transform.root
유니티 버그, 에러, 오류모음 (0) | 2020.07.20 |
---|---|
사소한 c# 테크닉 (0) | 2020.07.08 |
스파인 관련함수 (0) | 2020.07.02 |
//인스펙터에 script표시
GUI.enabled = false;
{
var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
}
GUI.enabled = true;
중괄호를 if문이나 for문같은게 없더라도 구획을 나누는데 쓰면 좋다
이렇게 만들어두면 필요할때 함수로 묶기도 편하다
region따위보다 가독성이 훨씬 좋다
그리고 아래는 아웃풋이 있을경우 예시
//worldPosition 2 screenPosition
Vector2[] screenPositions;
Vector2 screenHandlePosition;
{
screenPositions = System.Array.ConvertAll(worldPositions, wp => RectTransformUtility.WorldToScreenPoint(cam, wp));
screenHandlePosition = RectTransformUtility.WorldToScreenPoint(cam, worldHandlePoint);
}
foreach (var reloadEndSound in reloadEndSounds)
{
reloadEndSound.Play();
}
foreach는 무조건 var를 쓰자. 어차피 용도는 한정되어 있으니까
참조변수는 s만 빼서 쓰면 식별도 편하고 좋다
switch (humanBodyBones)
{
case HumanBodyBones.LeftUpperLeg:
case HumanBodyBones.RightUpperLeg:
case HumanBodyBones.LeftLowerLeg:
case HumanBodyBones.RightLowerLeg:
partDamage = 0.7f;
break;
case HumanBodyBones.Spine:
case HumanBodyBones.Chest:
case HumanBodyBones.UpperChest:
case HumanBodyBones.Hips:
partDamage = 1f;
break;
case HumanBodyBones.Neck:
case HumanBodyBones.Head:
partDamage = 2f;
break;
case HumanBodyBones.LeftShoulder:
case HumanBodyBones.RightShoulder:
case HumanBodyBones.LeftUpperArm:
case HumanBodyBones.RightUpperArm:
case HumanBodyBones.LeftLowerArm:
case HumanBodyBones.RightLowerArm:
partDamage = 0.7f;
break;
}
책이나 교수들이 스위치문 이상하게 알려주는데
조건마다 break 달 필요없다.
애초에 그럴거면 다중if 쓰지 뭐라러 스위치문을 쓰겠는가
public void PressButton(string enumName, int index)
{
Debug.Log($"PressButton({enumName}, {index})");
if (enumName == nameof(MainCategory))
{
mainCategory = (MainCategory)index;
}
if (enumName == nameof(CostumeCategory))
{
costumeCategory = (CostumeCategory)index;
}
if (enumName == nameof(AppearanceCategory))
{
appearanceCategory = (AppearanceCategory)index;
}
}
else if 대신 다중if를 쓰자.
가끔 switch문이 제약조건으로 안 먹는 경우 다중if를 많이 쓴다
오잉? '처리량이 늘어나는데 왜 else if를 안 쓰지?' 하고 의아해 할것이다.
보통 이렇게 수동으로 분기처리하는 데이터는 양이 적기 때문에
처리량이 늘어나도 거의 영향을 안 주는데
else if는 맨 윗열이 삭제되거나 하면 일일히 else를 지워가면서 해야한다
몰론 엄청나게 무거운 로직을 처리할땐 else if를 써야겠지만 그럴일은 별로 없다
아래는 또다른 예시
public void Skill(int index)
{
if (hp<=0)
{
return;
}
if (IsMine)
{
if (CurrentSkillDelay(index) > 0)
{
return;
}
for (int i = 0; i < 2; i++)
{
if (CurrentSkillTime(i) > 0)
{
return;
}
}
}
//스킬실행
}
만약 위 코드에 if else를 쓰고 작동부를 if블록 안쪽에 두었다면 엄청나게 복잡해졌을것이다
다중루프 탈출
변수둬서 if체크하며 탈출하지 말고
goto로 탈출하자
for (int i = 0; i < players.Length; i++)
{
for (int j = 0; j < bullets.Length; j++)
{
if (CollisionCheck(players[i], bullets[j]))
{
goto LOOP_OUT;
}
}
}
LOOP_OUT:;
자주 쓰는 유니티 코드 모음 (0) | 2020.07.09 |
---|---|
스파인 관련함수 (0) | 2020.07.02 |
Parent of RectTransform is being set with parent property (0) | 2020.06.29 |
스파인 컴포넌트 써오면서 깨달은점은 스파인 만든놈들은 유니티를 존나 못한단것이다
스파인 애니메이션 변경관련
using계열
using Spine.Unity
-스파인 애니메이션 변경시 해당 오브젝트 하위에 SkeletonAnimation이 있을경우
public SkeletonAnimation skeletonAnimation;
[SpineAnimation(dataField: "skeletonAnimation")]
public String spineAnim;
SkelAnim.AnimationName = spineAnim;
-스파인 애니메이션 변경시 다른 오브젝트에서 SkeletonAnimation를 호출할경우
(SkeletonAnimation타입)
public SkeletonAnimation skeletonAnimation;
public AnimationReferenceAsset spineAnim;
SkelAnim.loop = false; //루프는 반드시 애니메이션 설정전에 실행되어야함
SkelAnim.AnimationName = spineAnim.name;
(SkeletonGraphic타입)
public SkeletonGraphic skeletonGraphic;
public AnimationReferenceAsset spineAnim;
skeletonGraphic.AnimationState.SetAnimation(trackIndex:0, spineAnim.name, loop:false); //false는 루프, 0은 인덱스 번호
-현재 SkeletonAnimation의 애니메이션의 지속시간
(SkeletonAnimation타입)
SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
float Duration=skeletonAnimation.skeleton.Data.FindAnimation(skeletonAnimation.AnimationName).Duration;
(SkeletonGraphic타입)
SkeletonGraphic skelGrap = GetComponent<SkeletonGraphic>();
string animName = skelGrap.AnimationState.Tracks.Items[0].ToString();
float duration=skelGrap.SkeletonData.FindAnimation(animName).Duration;
스파인 특정 본의 y축 좌표 추적
skeletonGraphic.Skeleton.FindBone("본이름").Y * 100f;
스파인 스킨 변경
GetComponent<Spine.Unity.SkeletonGraphic>().Skeleton.SetSkin("스킨 이름");
스파인 스킨을 번호로 가져올때
var skeletonGraphic = GetComponent<Spine.Unity.SkeletonGraphic>();
var skins = skeletonGraphic.AnimationState.Data.SkeletonData.Skins.ToArray();
skeletonGraphic.Skeleton.SetSkin(skins[번호]);
해당 skeletonGraphic의 애니메이션 리스트 가져오기
skeletonGraphic.AnimationState.Data.SkeletonData.Animations.ToArray()
해당 skeletonGraphic의 스킨 리스트 가져오기
skeletonGraphic.AnimationState.Data.SkeletonData.Skins.ToArray()
SkeletonDataAsset을 가져올때
public Spine.Unity.SkeletonDataAsset skeletonDataAsset;
SkeletonDataAsset 변경
public Spine.Unity.SkeletonDataAsset skeletonDataAsset;
var skeletonGraphic = GetComponent<Spine.Unity.SkeletonGraphic>();
if(skeletonGraphic.skeletonDataAsset!= SkeletonDataAsset)
{
skeletonGraphic.skeletonDataAsset = SkeletonDataAsset;
skeletonGraphic.Initialize(true);
}
현재 애니메이션의 최대시간
SkeletonGraphic skeletonGraphic = GetComponent<SkeletonGraphic>();
if (skeletonGraphic.gameObject.activeInHierarchy && skeletonGraphic.IsActive())
{
float duration = skeletonGraphic.AnimationState.Tracks.Items[0].AnimationTime;
}
정지
skeletonGraphic.timeScale = 0;
if (skeletonGraphic.gameObject.activeInHierarchy && skeletonGraphic.IsActive())
{
skeletonGraphic.AnimationState.Tracks.Items[0].TrackTime = 0;
}
일시정지
skeletonGraphic.timeScale = 0;
재생
var entry = skeletonGraphic.AnimationState.SetAnimation(0, animation.Name, loop);
entry.MixDuration = 0f;
되감기
SkeletonGraphic skeletonGraphic = curtainNormal.GetComponent<SkeletonGraphic>();
if (skeletonGraphic.gameObject.activeInHierarchy && skeletonGraphic.IsActive())
{
float duration = skeletonGraphic.AnimationState.Tracks.Items[0].AnimationTime;
skeletonGraphic.unscaledTime = true;
skeletonGraphic.AnimationState.Tracks.Items[0].TrackTime = duration;
skeletonGraphic.timeScale = -1;
}
애니메이션이 끝났을때에만 재생(Update에 넣어야함)
if (skeletonGraphic.AnimationState.Tracks.Items.Length == 0)
{
var entry = skeletonGraphic.AnimationState.SetAnimation(0, animation.Name, loop);
entry.MixDuration = 0f;
skeletonGraphic.Initialize(true);
skeletonGraphic.Update(0f);
}
else
{
Spine.TrackEntry trackItemNow = skeletonGraphic.AnimationState.Tracks.Items[0];
trackItemNow.Loop = loop;
float duration = skeletonGraphic.SkeletonData.FindAnimation(trackItemNow.ToString()).Duration;
float trackTime = trackItemNow.TrackTime;
if (trackTime > duration-0.1f)
{
var entry = skeletonGraphic.AnimationState.SetAnimation(0, animation.Name, loop);
entry.MixDuration = 0f;
skeletonGraphic.Initialize(true);
}
}
애니메이션 종료 콜
단점은 루프가 꺼져있어도 애니메이션이 타임만 증가하며 영원히 돌아가는거로 나오기 때문에 작동을 제대로 안함
void Awake()
{
//애니메이션 루틴이 끝났을경우 호출(루프중이면 주기마다 호출됨)
GetComponent<SkeletonGraphic>().AnimationState.Complete -= SpineEndEvent;
GetComponent<SkeletonGraphic>().AnimationState.Complete += SpineEndEvent;
//애니메이션이 종료되었을경우 호출(제대로 작동 안 함)
GetComponent<SkeletonGraphic>().AnimationState.End -= SpineEndEvent;
GetComponent<SkeletonGraphic>().AnimationState.End += SpineEndEvent;
}
void SpineEndEvent(Spine.TrackEntry te)
{
//동작할 코드
}
스켈레톤 그래픽 사이즈
skeletonGraphic.SkeletonData.Width //가로
skeletonGraphic.SkeletonData.Height //세로
특정폴더의 스켈레톤 데이터를 전부 불러옴
#if UNITY_EDITOR
public static Spine.Unity.SkeletonDataAsset[] GetFolderToSkeletonDatas(UnityEngine.Object folder)
{
var folderPath = UnityEditor.AssetDatabase.GetAssetPath(folder);
var filePathSkeletonDatas = UnityEditor.AssetDatabase.FindAssets($"t:{typeof(Spine.Unity.SkeletonDataAsset).Name}", new string[] { folderPath });
var skeletonDatas = new Spine.Unity.SkeletonDataAsset[filePathSkeletonDatas.Length];
for (int i = 0; i < skeletonDatas.Length; i++)
{
skeletonDatas[i] = UnityEditor.AssetDatabase.LoadAssetAtPath<Spine.Unity.SkeletonDataAsset>(UnityEditor.AssetDatabase.GUIDToAssetPath(filePathSkeletonDatas[i]));
}
return skeletonDatas;
}
#endif
사소한 c# 테크닉 (0) | 2020.07.08 |
---|---|
Parent of RectTransform is being set with parent property (0) | 2020.06.29 |
SQLite 유니티 사용방법 (0) | 2020.05.24 |
new_go.transform.parent=target.transform.parent;
를 아래처럼 고침
new_go.transform.SetParent(target.transform.parent);
스파인 관련함수 (0) | 2020.07.02 |
---|---|
SQLite 유니티 사용방법 (0) | 2020.05.24 |
유니티 커스텀 인스펙터 (0) | 2020.05.19 |
안드로이드 스튜디오 안 깔아도 됨
유니티 스파인 오류 모음 (0) | 2020.07.24 |
---|---|
스파인 사용법 (0) | 2020.06.25 |
인풋필드 엔터누르면 초기화 (0) | 2020.05.31 |