사실 C++ 에서 enum을 많이 쓰는 이유는 enum자체가 int값이랑 별 다르지 않기 때문입니다. 예를 들어
enum eAnimal
{
ANIMAL_DOG,
ANIMAL_CAT
};
이 있으면 ANIMAL_DOG은 0, ANIMAL_CAT은 1에 불과할 뿐이죠.
int dogIndex = ANIMAL_DOG;
이런게 아무 문제 없이 되었으니까요. 이제는 C#부터 비롯한 다양한 언어에서(아마 C++ 차세세대 규격도 그랬던듯) enum을 strong type으로 다뤄서 저런게 쉽게 안되게 하긴 하는데 그래도..
int dogIndex = (int)ANIMAL_DOG;
하면 여전히 dogIndex는 0이 됩니다.
근데 C#에서 재밌는게 enum으로 부터 스트링 값을 뽑아올수가 있지요. 즉 ANIMAL_DOG을 실행중에 "ANIMAL_DOG"이라 문자열로 가져올수도 있는겁니다. 그래서 유니티를 만지면서 함 실험을 해봤습니다. 유니티에서 prefab을 만들면 그 값을 기억하는데 이때 enum 형을 기억하면 과연 문자열을 기억하는지 아니면 int로 기억하는지 궁금했어요.
사실 은근 string으로 저장되길 바랬습니다... string으로 저장하면 이런게 되거든요..
만약 prefab에 ANIMAL_CAT을 저장해눴는데.. 그 후에 eAnimal에 새로운 놈을 추가하면..
enum eAnimal
{
ANIMAL_DOG,
ANIMAL_MOO,
ANIMAL_CAT
};
나중에 그 prefab을 읽어와도 숫자 1이 아닌 "ANIMAL_CAT"으로 읽히기에 중간에 다른 놈을 삽입해도 아무 문제가 없다는거죠...
근데 실험해보니... ANIMAL_MOO가 읽히더군요 -_-;
뭐 그래서 유니티에서 prefab저장할때 enum은 int 저장되는겁니다... 뭐 이거의 장점도 있어요.... 이름 바꾸긴 편하죠.. ANIMAL_CAT을 ANIMAL_MEOW로 바꿔도 아무 문제가 없거든요.
그럼 이상 후다닥 -_-
2013년 7월 31일 수요일
2012년 6월 16일 토요일
Unity는 C#으로 작성했다?
요즘들어 Unity가 인기를 많이 끌고 있고, 저도 어쩌다 유니티를 주무르는 동안에 발견한 내용들을 짧게짧게 블로그에 올려볼 생각입니다. 유니티를 체계적으로 배우시고 싶다면 아마 게임개발포에버에서 도플광어님이 연재하시는 글을 보시는게 젤 좋을겁니다.
자, 그렇다면 오늘의 짧은 정보는... 과연 Unity는 어떤 언어로 작성되었나? 입니다. Unity가 Mono를 이용해서 .NET 프레임워크를 자체적으로 지원하고, 저희가 유니티에서 사용할 수 있는 스크립트 언어도 C# 이다보니
'유니티가 C#으로 작성 되었구나. 그럼 이 엔진이 속도가 너무 느리지 않을까?'
라는 걱정을 하는 분들이 계실겁니다. (저도 그랬다는..)
그래서 그에 대한 답을 좀 찾아보니 영문 질답란에 이미 유니티 개발자가 답을 해놨더군요.
이걸 대충 번역하면...
"유니티는 C++로 작성되었으나 다음과 같은 예외가 있습니다.
.NET API를 노출시켜서 여러분들이 C++로 게임을 짤 필요를 없게 만든 것 뿐이지요. 자바스크립트나 C# 또는 Boo를 이용해서 코딩을 할 수 있는 이유가 바로 .NET API 덕분입니다.
에디터 프로그램의 UI는 C#으로 작성했습니다. 유니티를 사용하시는 게임 개발자들에게 공개된 API와 거의 동일한 API를 쓰지요. (아직 공개되지 않는 API를 조금 쓰기도 합니다만 그리 많진 않습니다.)
이것이 바로 "UnityEngine.dll 파일을 다른 C# 프로젝트에서 사용할 수 있나요?"라는 질문에 대한 답이 언제나 "아니요"인 이유입니다. UnityEngine.dll에는 거의 아무 기능도 들어있지 않습니다. 이건 그저 C#/자바스크립트 호출들을 C++ 엔진에 연결해줄 뿐입니다. C++ 엔진이 없이는 그냥 속빈강정이랄까요?"
한마디로 대충 정리하면:
참조:
자, 그렇다면 오늘의 짧은 정보는... 과연 Unity는 어떤 언어로 작성되었나? 입니다. Unity가 Mono를 이용해서 .NET 프레임워크를 자체적으로 지원하고, 저희가 유니티에서 사용할 수 있는 스크립트 언어도 C# 이다보니
'유니티가 C#으로 작성 되었구나. 그럼 이 엔진이 속도가 너무 느리지 않을까?'
라는 걱정을 하는 분들이 계실겁니다. (저도 그랬다는..)
그래서 그에 대한 답을 좀 찾아보니 영문 질답란에 이미 유니티 개발자가 답을 해놨더군요.
이걸 대충 번역하면...
"유니티는 C++로 작성되었으나 다음과 같은 예외가 있습니다.
.NET API를 노출시켜서 여러분들이 C++로 게임을 짤 필요를 없게 만든 것 뿐이지요. 자바스크립트나 C# 또는 Boo를 이용해서 코딩을 할 수 있는 이유가 바로 .NET API 덕분입니다.
에디터 프로그램의 UI는 C#으로 작성했습니다. 유니티를 사용하시는 게임 개발자들에게 공개된 API와 거의 동일한 API를 쓰지요. (아직 공개되지 않는 API를 조금 쓰기도 합니다만 그리 많진 않습니다.)
이것이 바로 "UnityEngine.dll 파일을 다른 C# 프로젝트에서 사용할 수 있나요?"라는 질문에 대한 답이 언제나 "아니요"인 이유입니다. UnityEngine.dll에는 거의 아무 기능도 들어있지 않습니다. 이건 그저 C#/자바스크립트 호출들을 C++ 엔진에 연결해줄 뿐입니다. C++ 엔진이 없이는 그냥 속빈강정이랄까요?"
한마디로 대충 정리하면:
- 유니티 내부는 C++이여서 C#보단 성능이 빠릅니다. 단, C#/C++ 컨텍스트 스위치 되는 부분에서 약간의 성능저하는 있을수 있습니다만 언리얼엔진에 비해 크게 문제는 안될거 같습니다.
- 유니티 에디터는 C#으로 작성되어 있습니다. (에디터에서 리플렉션을 자동으로 지원해주는것도 이때문일듯...)
- 유니티를 사랑합니다.. (응?)
참조:
2012년 6월 11일 월요일
2012년 2월 6일 월요일
유니티에서 topology가 같은 캐릭터간에 애니메이션 공유하기...
![]() |
이미지 출처: http://answers.unity3d.com/questions/191282/sharing-animations-between-models.html |
본(bone)의 길이가 다른 캐릭터들 사이에서 애니메이션을 공유하려고 한다고 생각해 보죠. 물론 각 캐릭터마다 애니메이션을 따로 만들어주면 좋겠지만 인력이 부족한다던가... 그런데 이렇게 본의 길이가 다른 캐릭터터들 사이에서 애니메이션을 공유할 수 있을까요? 뭐 되니까 이글을 쓰는거죠... -_-; 평행이동과 확대/축소를 사용하지 않으면 가능합니다. 달리 말하면 회전만 이용하면 된다는거죠. 이렇게 생각해보면 이해가 쉬워요. 본인의 오른쪽 팔꿈치를 안쪽으로 90도만큼 회전시켜 보세요. 이제 본인보다 키가 작은 친구에게 똑같이 오른쪽 팔꿈치를 90도만큼 회전시키라고 하는거죠. 그러면 둘의 포즈가 똑같죠? 바로 이 원리 입니다. 이해 되죠?
결국 3DS Max가 뱉어내는 데이터가 어쨌던간에 애니메이션에서 회전만 적용시킬 수 있는 방법만 있으면 되는건데... 유니티에서 이런 걸 공식적으로 지원해주는 찾으려고 포럼을 뒤졌지만 그런것 같진 않더군요. 그러면 파이프라인 어딘가에서 회전 이외의 키프레임 정보를 지워버리는 방법이 없을까 찾아봤지요. 불행히도 딱히 대답을 찾을 순 없었습니다.
뭐든간에 좋은소식은...... 제가 그 꼼수를 찾아냈다는 거지요. 무핫핫..... :D
이렇게 했답니다. (코드는 조 밑에~)
- Asset/Editor 폴더 안에 ConvertToRotationOnlyAnim.cs 라는 스크립트 파일을 만듭니다.
- 이 스크립트를 호출하는 메뉴 항목을 만듭니다.
- Unity에 애니메이션을 import 해옵니다. (Unity가 애니메이션 파일이라고 생각하는 한 어디서 이 애니메이션을 만들었는지는 상관없습니다.)
- import해온 애니메이션 애셋에 마우스 오른쪽 버튼을 누르고, 단계 #2에서 추가했던 메뉴 아이템을 선택합니다.
- 이제 스트립트 안에서 propertyName 필드 중에 "m_LocalRotation"이란 이름을 포함한 놈만 복사합니다.
- 이제 _rot 애니메이션 클립을 게임오브젝트의 애니메이션 컴포넌트에 대입합니다.
- 시작 버튼을 누르고..... 즐거워 해봅시다.. 얼씨구나.. 지화자~ -_-
그리고 이게 위에서 말씀드린 스크립트의 전체 소스코드. 주석을 잘 달아놨으니 영어공부할겸..... 대충 보고 이해하세요. ㄱ ㄱ ㅑ ~ -_-
using UnityEditor;
using UnityEngine;
using System.IO;
public class ConvertToRotationOnlyAnim
{
[MenuItem("Assets/Convert To Rotation Animation")]
static void ConvertToRotationAnimation()
{
// Get Selected Animation Clip
AnimationClip sourceClip = Selection.activeObject as AnimationClip;
if (sourceClip == null)
{
Debug.Log("Please select an animation clip");
return;
}
// Rotation only anim clip will have "_rot" post fix at the end
const string destPostfix = "_rot";
string sourcePath = AssetDatabase.GetAssetPath(sourceClip);
string destPath = Path.Combine(Path.GetDirectoryName(sourcePath), sourceClip.name) + destPostfix + ".anim";
// first try to open existing clip to avoid losing reference to this animation from other meshes that are already using it.
AnimationClip destClip = AssetDatabase.LoadAssetAtPath(destPath, typeof(AnimationClip)) as AnimationClip;
if (destClip == null)
{
// existing clip not found. Let's create a new one
Debug.Log("creating a new rotation only animation at " + destPath);
destClip = new AnimationClip();
destClip.name = sourceClip.name + destPostfix;
AssetDatabase.CreateAsset(destClip, destPath);
AssetDatabase.Refresh();
// and let's load it back, just to make sure it's created?
destClip = AssetDatabase.LoadAssetAtPath(destPath, typeof(AnimationClip)) as AnimationClip;
}
if (destClip == null)
{
Debug.Log("cannot create/open the rotation only anim at " + destPath);
return;
}
// clear all the existing curves from destination.
destClip.ClearCurves();
// Now copy only rotation curves
AnimationClipCurveData[] curveDatas = AnimationUtility.GetAllCurves(sourceClip, true);
foreach (AnimationClipCurveData curveData in curveDatas)
{
if (curveData.propertyName.Contains("m_LocalRotation"))
{
AnimationUtility.SetEditorCurve(
destClip,
curveData.path,
curveData.type,
curveData.propertyName,
curveData.curve
);
}
}
Debug.Log("Hooray! Coverting to rotation-only anim to " + destClip.name + " is done");
}
}
피드 구독하기:
글 (Atom)