dll은 프로젝트폴더의 Debug폴더에 있다. 디버그가 싫으면 릴리즈로 하면 릴리즈 폴더에 생긴다
dll만 쓸거면 dll만 뽑으면 됨
불러오기 위해 C#폴더에 넣을건데 C#은 경로가 조금 다르다
프로젝트 폴더/프로젝트이름 폴더/bin/Debug 폴더에 넣는다
프로젝트 폴더가 두개있는게 이상하지만 얘내가 그렇게 만든거니까 그러려니 하자
불러올때
using System;
using System.Windows.Forms;
namespace Dll_Import_Test
{
static class Program
{
/// <summary>
/// 해당 응용 프로그램의 주 진입점입니다.
/// </summary>
[System.Runtime.InteropServices.DllImport("user32.dll")] //키보드 상태
public static extern int GetKeyboardState(byte[] pbKeyState);
[System.Runtime.InteropServices.DllImport("Dll_Export_Test.dll")]
public static extern int m_test8();
[System.Runtime.InteropServices.DllImport("Dll_Export_Test.dll")]
public static extern void m_test38(int[] _array);
[STAThread]
static void Main()
{
if (m_test8() == 8)
{
MessageBox.Show("m_test8() == 8");
}
else
{
MessageBox.Show("m_test8() 읽기 에러");
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
동일 DLL에서 여러 함수를 불러오는 예제와 윈도우즈에 포함된 DLL을 불러오는 예제로 되어있다
ㅇ
38버전은 dll에서 배열로드버전이다
// Dll_Export_Test.cpp: 콘솔 응용 프로그램의 진입점을 정의합니다.
//
#include <windows.h>
#include "stdafx.h"
//extern은 내보낸다는 소리
//"C"은 C언어 규약으로 작성이랬던가 확실하지 않음, 이거 안넣으면 읽기실패
//__declspec(dllexport)은 dll로 내보내겠다는 뜻
//__stdcall 이건 호출방식인데 일반적으로 C#에선 __stdcall을씀(c++ 기본값은 __cdecl)
extern "C" __declspec(dllexport) void __stdcall m_test38(int _array[])//완성판
{
for (int i = 0; i < 8; i++)
{
_array[i] = i;
}
return;
};
40버전은 길이를 입력받아서 처리하는거, 가능하면 자동화하고 싶었지만
C++의 배열시스템이 너무 후진적이라 이따구로 함
배열포인터에는 길이정보가 없다고 하니까 더 많은걸 바라지 말아라.
extern "C" __declspec(dllexport) void __stdcall m_test40(int _array[],int _length)
{
for (int i = 0; i < _length; i++)
{
_array[i] = i;
}
return;
};
불러올떄
using System;
using System.Windows.Forms;
namespace Dll_Import_Test
{
static class Program
{
/// <summary>
/// 해당 응용 프로그램의 주 진입점입니다.
/// </summary>
[System.Runtime.InteropServices.DllImport("Dll_Export_Test.dll")]
public static extern void m_test40(int[] _array,int _length);
[STAThread]
static void Main()
{
var _array = new int[16];
m_test40(_array, _array.Length);
MessageBox.Show($"m_test40(): [{string.Join(", ", _array)}]");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
using UnityEngine;
public class ChangeStateChecker : StateMachineBehaviour
{
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On State Enter");
}
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On State Exit");
}
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On State Update");
}
override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On State Move");
}
override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("On State IK");
}
}
GetComponent<Animator>().Play("StateName"); //State이동(실행)
animator.Play("StateName",-1,0); //재생취소후 재생
characterSpine.GetComponent<Animator>().SetBool("ParameterName", boolValue); //파라미터 bool 설정
var animator = coordinator.animator;
var layer = animator.GetLayerIndex("Base Layer");
var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
var time = 1.2f;
var normalizedTime = time / animatorStateInfo.length;
animator.Play(animatorStateInfo.shortNameHash, layer, normalizedTime);
적용예제
void JumpAnimation(float jumpTime)
{
var layer = animator.GetLayerIndex("Base Layer");
var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
animator.Play(animatorStateInfo.shortNameHash, layer, jumpTime / animatorStateInfo.length);
}
애니메이터 현재 재생시간
var layer = animator.GetLayerIndex("Base Layer");
var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(layer);
float time = animatorStateInfo.length * animatorStateInfo.normalizedTime;//(애니메이션 길이) * (0~1시간)
var weight = 1f;
var lerpSpeed = 1f;
var layer = animator.GetLayerIndex("Base Layer") ;
animator.SetLayerWeight(layer, Mathf.Lerp(animator.GetLayerWeight(layer), weight, lerpSpeed));
애니메이터 보호장치, 근데 이딴거 쓰지말고 아래 이미지를 써라
public class AnimationStateProtector : MonoBehaviour
{
Animator animator;
int lastState = 0;
int enableCount = 0;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
var animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);
lastState = animatorStateInfo.shortNameHash;
}
void OnEnable()
{
if (enableCount!=0)
{
animator.Play(lastState);
}
enableCount++;
}
}
디버그모드에서 켜면 보인다. 위와 동일한 기능임
애니메이터 스테이트 변동 체크
void OnEnable()
{
StartCoroutine(CharacterAnimatorStateChengedChecker());
}
[System.Serializable]
public class AnimatorStateInfoEvent : UnityEngine.Events.UnityEvent<AnimatorStateInfo> { }
public AnimatorStateInfoEvent OnAnimatorStateChengedEvent;
public IEnumerator AnimatorStateChengedChecker()
{
while (true)
{
var fullPathHashPrevious = GetComponent<Animator>().GetCurrentAnimatorStateInfo(layerIndex:0).fullPathHash;
yield return new WaitUntil(() => GetComponent<Animator>().GetCurrentAnimatorStateInfo(layerIndex: 0).fullPathHash != fullPathHashPrevious);
OnAnimatorStateChengedEvent.Invoke(GetComponent<Animator>().GetCurrentAnimatorStateInfo(layerIndex: 0));
}
}
부위 가져오기
var transform=Animator.GetBoneTransform(HumanBodyBones.Hips);
BlendTree를 읽어서 인스펙터에 업데이트
public List<Emote> emotes;
public Animator animator;
[System.Serializable]
public class Emote
{
//public Animation animation;
public AnimationClip animation;
public Sprite icon;
public float threshold;
}
public AnimationClip[] EmoteAnimations
{
get
{
return emotes.ConvertAll(x=>x.animation).ToArray();
}
}
#if UNITY_EDITOR
public UnityEditor.Animations.AnimatorController animatorController;
[ContextMenu("ImportFromBlendTree")]
public void ImportFromBlendTree()
{
var layerIndex = 0;
var stateName = "Emote";
{
//var animatorController = animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
var layer = animatorController.layers[layerIndex];
var states = layer.stateMachine.states;
var state = System.Array.Find(states, x => x.state.name == stateName);
//var blendTrees = System.Array.ConvertAll(states, state => state.state.motion as UnityEditor.Animations.BlendTree);
//blendTrees = System.Array.FindAll(blendTrees, blendTree => blendTree != null);
var blendTree = state.state.motion as UnityEditor.Animations.BlendTree;
var motions = System.Array.ConvertAll(blendTree.children, children => children.motion);
for (int i = 0; i < motions.Length; i++)
{
var motion= motions[i];
var animation = motion as AnimationClip;
var emoteIndex = emotes.FindIndex(x => x.animation == animation);
if (emoteIndex == -1)
{
var emote = new Emote();
emote.animation = animation;
emoteIndex = emotes.Count;
emotes.Add(emote);
}
emotes[emoteIndex].threshold = (float)i/motions.Length;
}
}
UnityEditor.EditorUtility.SetDirty(this);
}
#endif
이 버전은 Google Play 64비트 요구사항을 준수하지 않습니다. 다음 APK 또는 App Bundle은 64비트 기기를 지원하지만, 32비트 네이티브 코드만 포함합니다. [1] 앱에 64비트 및 32비트 네이티브 코드를 포함하세요. Android App Bundle 게시 형식을 사용하여 각 기기 아키텍처가 자동으로 필요한 네이티브 코드만 수신하도록 하세요. 그래야 앱의 전체 크기를 줄일 수 있습니다.