'Developer/GAME'에 해당되는 글 41건

  1. 2006/03/29 글뻥 C# vs C++ in Game Engine (4)
작년 이맘때쯤에 JAVA와 유니티3D를 연동하는 예제를 포스팅하였다.
짜증나는자바1편짜증나는자바2편

자바연동 2편에서 대충 Jar파일을 만들어서 Java에서 호출하는 부분을 만들었었지만, 1편에서 밝힌 바와 같이 Jar를 유니티3D로 끌고 와서 연동하는 예제는 다루지 않았다.

어쩌면... 짜증나는 자바시리즈 3편으로 봐도 될 정도로 오늘 다룰 주제는 자바로 만들어진 Jar파일을 유니티로 가져와서 연동하는 예제이다.

( 출처 밝히면 펌 자유이지만, 출처를 밝히지 않으신다면 고소크리 들어갑니다.)

1. 이클립스를 연다.
2. Android Application Project를 새로 만든다.
사용자 삽입 이미지
3. 이름과 프로젝트명을 지정하고 패키지이름을 지정한다.
사용자 삽입 이미지
4. 이제부터 다음, 다음, 다음, 다음 4연타.
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지

5. 프로젝트 생성완료. (쉽죠?)
사용자 삽입 이미지
6. 디버그 설정을 Android Application으로 설정
사용자 삽입 이미지
7. 이제 만들어진 프로젝트명에서 마우스 우클릭후 속성을 클릭
사용자 삽입 이미지
8. "Is Library"체크하고 "Apply" 한번 눌러 준뒤 "OK"
사용자 삽입 이미지
9. 프로젝트 폴더 밑에 /bin 폴더에 보면 "Plugin.jar"파일이 생성되어 있다. (나중에 유니티에서 이녀석을 가져다 쓸거임)
사용자 삽입 이미지
10. /src/com.lingo.plugin을 클릭한 후 다시 우클릭하여 New, Class를 차례대로 클릭
사용자 삽입 이미지
11. 클래스명을 Test로 하고 Finish 클릭
사용자 삽입 이미지
12. 다음과 같이 정적(Static) 메소드와 인스턴스(Static이 안붙은) 메소드를 작성한다.
사용자 삽입 이미지

13. 다음과 같이 Build Automatically 선택되어 있으면 저장과 동시에 자동으로 Build 됨.
     * Console에서 에러가 발생하지 않았다면 문제없이 사용가능한 형태가 됨.
사용자 삽입 이미지

14. 저장하고 빌드가 완료되면 /bin 폴더의 속성을 클릭해서 실제 경로 확인
사용자 삽입 이미지
15. 이제 유니티로 와서 코딩부터...
     * 주의점은 Static은 "AndroidJavaClass"로, 인스턴스는 "AndroidJavaObject"로 선언되어야 함.
사용자 삽입 이미지
18. 다음과 같이 Main Camera와 GUI Text만 배치한다.
사용자 삽입 이미지
19. PluginTest 파일을 Main Camera에 Attach한후 GUI Text를 다시 Asign한다.
     - 물론 /Pluings/Android 밑에 "9"에서 언급한 plugin.jar 파일을 넣어두는걸 잊으면 골룸.
사용자 삽입 이미지
20. GUI Text Default
사용자 삽입 이미지

21. Editor 상에서는 이렇게 보임. (문구가 장난이지만... 진짜 작동하는거 맞다. ㅜㅜ)
사용자 삽입 이미지
이제 마지막으로 Build&Run하면, 안드로이드 폰에서 실행된 결과를 확인할 수 있다.

2014/04/10 18:16 2014/04/10 18:16
유니티 공식문서에 있는 예제가 Giral 이라서 수정해서 사용중...
원링크 : http://docs.unity3d.com/Documentation/Manual/Input.html
하단에 보면 Low Pass Filter 부분이 있는데 엉망임...
var AccelerometerUpdateInterval : float = 1.0 / 60.0;
var LowPassKernelWidthInSeconds : float = 1.0;

private var LowPassFilterFactor : float = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds; // tweakable
private var lowPassValue : Vector3 = Vector3.zero;
function Start () {
lowPassValue = Input.acceleration;
}

function LowPassFilterAccelerometer() : Vector3 {
lowPassValue = Mathf.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor); //문제부분
return lowPassValue;
}
여기서 문제는 바로 Mathf.Lerp 즉, 선형보간 함수의 사용법이 틀렸다.
정확히는 Mathf.Lerp(float, float, float) 형태로 정의되어야 하는데 실제 들어가는 값은 무려 Vector3 타입!
따라서, 본 예제는 다음과 같이 수정되어야 한다.
lowPassValue = Mathf.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor); //문제부분
lowPassValue = Vector3.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor); //수정된 부분
이를 활용한 모바일 Tilt 예제는 다음과 같다.
using UnityEngine;
using System.Collections;

public class Behavior_Cam_Tilt : MonoBehaviour {
    public Transform _dog;
    Vector3 _InitPos;
    float _beforeX = 0f;
    private float _Velocity = 0.0F;
    float AccelerometerUpdateInterval = 1f / 60f;
    float LowPassKernelWidthInSeconds = 1f;

    private float LowPassFilterFactor = 0f;
    //private Vector3 lowPassValue = Vector3.zero;
    private float lowPassValue = 0f;

    void Start()
    {
        _InitPos = transform.position;
        LowPassFilterFactor = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds * 1.5f;
     }
     
     float LowPassFilterAccelerometer() {
        lowPassValue = Mathf.Lerp(lowPassValue, Input.acceleration.x, LowPassFilterFactor);
        return lowPassValue;
     }
     
     void Update(){
         SetTiltAngle();
     }
 
     void SetTiltAngle()
     {
       float _Accx = LowPassFilterAccelerometer();
       if (Mathf.Abs(_Accx) > 0.45f) return;
       float _length = 6.632358f; //원래는 계산해야 하지만, 삼각함수 값은 상수로 쓰는게 빨라서 45도 각도에 대한 상수값과 거리를 계산한 결과임.
       if (_Accx >= 0f) {
            transform.position = Vector3.Slerp(_InitPos, new Vector3(_length * -1f, 1.8f, _length), _Accx);
       } else {
            transform.position = Vector3.Slerp(_InitPos, new Vector3(_length, 1.8f, _length), _Accx * -1f);
       }
       transform.LookAt(new Vector3(_dog.position.x, _dog.position.y + 0.73f, _dog.position.z));
       _beforeX = _Accx;
     }
}
2014/04/08 15:04 2014/04/08 15:04
1인칭 시점으로 마구잡이 돌릴때...

* 오큘러스 카메라 앵글에 사용

using UnityEngine; 
using System.Collections; 
public class Behavior_Cam_Tilt : MonoBehaviour { 
     private Quaternion cameraBase = Quaternion.Euler(new Vector3(3f, 180f, 0f)); 
     private Quaternion referanceRotation = Quaternion.identity; 
     private const float lowPassFilterFactor = 0.2f; 
     void Start() { Input.gyro.enabled = true; } 
     void Update() {
           //transform.rotation = ConvertRotation(Input.gyro.attitude);
           transform.rotation = Quaternion.Slerp(transform.rotation, cameraBase * (ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), lowPassFilterFactor); 
      } 

     private static Quaternion ConvertRotation(Quaternion q) { 
           return new Quaternion(q.x, q.y, -q.z, -q.w); 
     } 
     private Quaternion GetRotFix() { 
            if (Screen.orientation == ScreenOrientation.Portrait) return Quaternion.identity; 
            if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.Landscape) return Quaternion.Euler(0, 0, -90); 
            if (Screen.orientation == ScreenOrientation.LandscapeRight) return Quaternion.Euler(0, 0, 90); 
            if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) return Quaternion.Euler(0, 0, 180); 
            return Quaternion.identity; 
      } 
}
2014/04/07 17:27 2014/04/07 17:27
개발비 없어요...
그냥 혼자 덕질덕질하며 그래픽 리소스 준비중입니다. ㅋ
예전에 비해서... 몇개 추가한 버전

- ToDo
   . 바르샤바조약군 (X종)
   . Tank류 : M1A1, M60
   . 자주포류 : M109A2, M1064
   . 견인포 : 105mm, 155mm
   . 보병 : 저격수

사용자 삽입 이미지
장르는 턴제 모바일 전략게임입니다.
게임제목은 스틸레인(가제). =)
2014/04/01 18:31 2014/04/01 18:31
근래에 새로운 프로젝트에 들어가는 바람에 강좌 업데이트가 안되서 죄송합니다.
모바일에서 3D게임이 조금씩 고급으로 치닫는 바람에 공부해야할게 너무나 많네요.

오늘은 간단히 Code로 Mesh를 생성해보겠습니다.

일단, Mesh라는 녀석을 정확히 한번 따져보겠습니다.
Mesh란 Wiki에 따르면 (http://en.wikipedia.org/wiki/Polygon_mesh) 이러합니다.

A polygon mesh is a collection of vertices, edges and faces that defines the shape of a polyhedral object in 3D computer graphics and solid modeling.

* 폴리곤 메쉬는 버티컬들과 엣지들과 면들을 3D컴퓨터 그래픽/솔리드모델링에서 사용하는 다면체의 모양의 집합이다.

뭐... 번역이 어려워서 글치 결국 폴리곤이라는 녀석을 모아 놓은게 폴리곤 메쉬 즉, 우리가 흔히 이야기하는 메쉬가 되겠습니다.

이럴때는 어려운 말 한마디 보다 다음의 Vertex-Vertex Meshes의 예를 한번 보죠.

* Vertex-Vertex Meshes의 예
사용자 삽입 이미지
점 9개가 보여서 하나의 육면체를 이루고 있습니다.
정확하게는 다음과 같이 구성되어 있습죠. 네네...
사용자 삽입 이미지


Vertex는 점입니다. 이 점들을 이은 선이 접선 또는 Edge하고 하고 이렇게 Edge가 보이면 면(Face)가 되고 Face가 2개 이상 모이면 면(Surface)가 됩니다. 다시 면들을 모으면 폴리곤 메쉬가 됩니다. (쉽죠?)

암튼 우리는 개발자니까(?)... 데이터구조에 관심을 가져봅시다.

첫 번째 예제를 보면 좌측에 Vertex List에 대한 데이터까지 상세하게 정의되어 있군요!
V0값은 Vector3좌표와 인접한 Vertex의 Index를 가지고 있습니다.

이제 이걸 기초로 메쉬 한번 만들어 봅시다.
물론 처음부터 육면체 만들자고 하면 서로 머리 복잡하니, Vertex 4개로 구성된 작은 4각형 메쉬를 만들겁니다.

먼저 빈 게임오브젝트 1개를 만들어 봅시다.
사용자 삽입 이미지
만들어진 빈 게임오브젝트에 Mesh Compoent인 Mesh Filter와 Mesh Renderer를 추가합니다.
사용자 삽입 이미지
- Mesh Filter는 Mesh의 데이터를 저장합니다.
- Mesh Renderer는 렌더링을 Mesh Filter에 있는 데이터로 렌더링을 담당하죠.

그리고 인식하기 쉽게 게임오브젝트의 이름을 "Mesh"라고 변경합니다.
아래의 예를 보면 Mesh Filter Components에는 "None (Mesh)"라고 되어 있는게 보이실 겁니다.

사용자 삽입 이미지
이제 여기 "Mesh Filter"에다가 데이터를 넣어 봅시다.

C# 스크립트를 하나 만들고 다음과 같이 코딩합니다.

using UnityEngine;
using System.Collections;
//List Collection을 사용하기 위해 Generic도 사용합니다.
using System.Collections.Generic;

public class MeshGen : MonoBehaviour {

    //ArrayList도 괜찮지만 편의상 List 객체로 선언해둡시다.
    //버텍스들의 위치를 저장할 객체입니다.
    public List<Vector3> _Vertex = new List<Vector3>();
    //다른 인접 버텍스의 Index값입니다.
    public List<int> _Tri = new List<int>();
    private Mesh mesh;

	// Use this for initialization
	void Start () {
        //시작하면 MeshFilter Compoent를 가져옵니다.
        mesh = GetComponent<MeshFilter>().mesh;

        //Position 값들인데, 편의상 풀었습니다.
        float x = transform.position.x;
        float y = transform.position.y;
        float z = transform.position.z;


        _Vertex.Add(new Vector3(x, y, z));
        _Vertex.Add(new Vector3(x + 1, y, z));
        _Vertex.Add(new Vector3(x + 1, y - 1, z));
        _Vertex.Add(new Vector3(x, y - 1, z));

         //이제부터는 버텍스 인덱스입니다.
         //이건 예제 코드 뒤에 설명하겠습니다.
         //1번 폴리곤
        _Tri.Add(0);
        _Tri.Add(1);
        _Tri.Add(3);
         //2번 폴리곤
        _Tri.Add(1);
        _Tri.Add(2);
        _Tri.Add(3);

        //메쉬를 청소해줍니다.
        mesh.Clear();
        //버텍스 데이터를 배열로 밀어 넣습니다.
        mesh.vertices = _Vertex.ToArray();
        //인접한 버텍스 데이터를 배열로 밀어 넣습니다.
        mesh.triangles = _Tri.ToArray();
        //메쉬를 생성합니다.
        mesh.Optimize();
        mesh.RecalculateNormals();
	}
}


실행해보면...
사용자 삽입 이미지
요롷콤 메쉬가 생성되어 있고,
Mesh 게임오브젝트 역시, 다음과 같이 값이 잘 들어가 있군요!
사용자 삽입 이미지
이제 인접 Index 값의 비밀을 알려드리죠.
비밀은 간단하게도 일종의 규칙입니다.
Polygon이 되려면 3개의 점이 있어야 합니다. 따라서, 그걸 간단히 3개씩 잘라서 사용하는 거죠.
사용자 삽입 이미지
실제로 다음과 같이 소스를 수정해보면...


        _Tri.Add(0);
        _Tri.Add(1);
        _Tri.Add(3);
        _Tri.Add(1);
        _Tri.Add(2);
        //_Tri.Add(3);


이런 상큼한 에러를 볼 수 있습니다.
사용자 삽입 이미지
"삼각형은 반드시 3의 배수여야 한다."

추가 설명은 여기까지 하고 이제 저 뻘건 녀석에게 옷을 입힐 차례입니다.
먼저 사용할 Texture가 있어야 겠지요?

깔끔한 128X128 px 짜리 체커입니다.
사용자 삽입 이미지



일반적으로 많이 사용하는 텍스쳐 Import후, Drag&Drop으로 게임오브젝트에 밀어 넣습니다.

사용자 삽입 이미지

플레이해보면... 어라?

사용자 삽입 이미지

예상과 다르게 시커먼 녀석만 올라왔네요.
이는 mesh데이터에 UV값을 넣지 않아서 생기는 현상입니다.
이제 UV값을 받을 수 있도록 소스를 추가해봅시다.


using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MeshGen : MonoBehaviour {

    public List<Vector3> _Vertex = new List<Vector3>();
    public List<int> _Tri = new List<int>();
    public List<Vector2> _UV = new List<Vector2>();
    private Mesh mesh;

    //Cell간의 Gap입니다. 5by5짜리 텍스쳐니까 간단히 1/5 = 0.2!
    private float _cellGap = 0.2f;
    //cell들의 Index를 저장합니다.
    public List<Vector2> _cell = new List<Vector2>();

    void Start () {
        mesh = GetComponent<MeshFilter>().mesh;

        float x = transform.position.x;
        float y = transform.position.y;
        float z = transform.position.z;


        _Vertex.Add(new Vector3(x, y, z));
        _Vertex.Add(new Vector3(x + 1, y, z));
        _Vertex.Add(new Vector3(x + 1, y - 1, z));
        _Vertex.Add(new Vector3(x, y - 1, z));

        _Tri.Add(0);
        _Tri.Add(1);
        _Tri.Add(3);
        _Tri.Add(1);
        _Tri.Add(2);
        _Tri.Add(3);

         //셀은 2개만 사용할겁니다. 0,0에 있는 검은색과 0,1에 있는 흰색입니다.
        _cell.Add(new Vector2(0, 0));
        _cell.Add(new Vector2(0, 1));

         //텍스쳐의 좌표를 UV에 넣습니다.
         //만약 List 인덱스 0번이라면 (0,0), (0.2,0), (0, 0.2), (0.2, 0.2)의 값을 가지겠죠?
        _UV.Add(new Vector2(_cellGap * _cell[1].x, _cellGap * _cell[1].y + _cellGap));
        _UV.Add(new Vector2(_cellGap * _cell[1].x + _cellGap, _cellGap * _cell[1].y + _cellGap));
        _UV.Add(new Vector2(_cellGap * _cell[1].x + _cellGap, _cellGap * _cell[1].y));
        _UV.Add(new Vector2(_cellGap * _cell[1].x, _cellGap * _cell[1].y));

        mesh.Clear();
        mesh.vertices = _Vertex.ToArray();
        mesh.triangles = _Tri.ToArray();
        //UV값을 넣습니다.
        mesh.uv = _UV.ToArray(); 
        mesh.Optimize();
        mesh.RecalculateNormals();
        }
}


이제 끝!
실행결과 입니다.

사용자 삽입 이미지
2014/02/23 16:47 2014/02/23 16:47
유니티3D + Mono Develop 을 사용하다보면 간혹 명령상에 문제가 없음에도 스크립트가 오작동 할때가 있습니다.
컴파일러의 에러는 없지만, 예상대로 작동하지 않는 문제입니다.

여러번 테스트한 결과 다음과 같은 경우 오작동 할 확률이 높습니다.

//예제임
string a = "abcd";

아주 간단한 코드인데 제대로 작동할 때도 있고 안될 때도 있습니다.
이걸 이렇게 바꾸면 또 작동됩니다.

//Example
string a = "abcd";


또는

//예제임.
string a = "abcd";


아마도, 2byte 코드의 경우 모노디펠롭이 정상적으로 인식하지 못하는 상황이 되는 것 같습니다.
특히, 소스를 쉐어할 경우 개발자 자리에서는 잘되는데 소스를 새로 받으신 분의 자리에서는 안된다던가...
이런경우에 반듯이 한글을 사용한 뒤에 "."을 찍어두시면 해결이 가능할 것입니다.

그럼에도 저는 Visual Studio로 개발하시라고 말씀드리고 싶네요.
그리고 가능하시면 한글 주석 사용하지 마세욤.
저장방식은 우쨌든 "UTF-8"!!

2014/01/06 13:47 2014/01/06 13:47
안녕하세요? 글뻥입니다.
먼저 동영상 하나 보고 본론 말씀드리겠습니다.



최근 이걸 만든 회사에서 일하고 있습니다.
현재하고 있는 일은 "인공생명체를 만들어 육성하고 교배해서 새로운 생명체를 만들어내는 메커니즘으로 게임을 구현하고 있습니다."

개발은 유니티로 할 생각이며, 이 인공생명체의 학습엔진부터 설계해서 최종적으로는 주인의 피드백에 따라 학습하는 생명체입니다. 이는 다시 유전되어 자식세대에 물려 줍니다.

작지만, 무한 게임이 가능한 아이디어라 생각합니다.

흔하디 흔한 카카오톡 게임은 아니고, 해외향으로 만들어질 예정입니다.

요건은 다음과 같습니다.

근무지 : 양재동
채용인원 : 기획자 O명, 3D 모델링/애니메이터 O명(R&D 능력 보유, 유니티 신기능 또는 제가 만든 엔진 테스트 지원, 콘텐츠 제작 표준화 업무), 개발자 O명 (유전알고리즘 또는 학습모델에 대한 이해가 있으신분이며 C# 프로젝트 유경험자로 잘하신 필요는 없습니다.)

다음과 같은 분은 지원을 자재부탁드립니다.

1. 혼자 일하는게 편하신 분
2. 문제를 혼자 떠안고 자폭하시는 분
3. 시키는것만 하겠다는 분


(저는 노예와 일하고 싶지 않습니다.)


지원처 : vicviper@live.co.kr / vicviper@lingogames.net
2013/12/09 23:50 2013/12/09 23:50
이바닥이 재미 있는건 게임제작자들이 제대로된 표준도 없이 게임을 개발하고 있다는 점일거라 생각된다.
영화에서도 시나리오, 대본, 콘티 등이 있는데...
CF도 마찬가지 인데도...

게임은 없다. (정말이다.)
각각의 요소들이 어떻게 미적인 요소와 코드로 연결되는지에 대한 Workflow가 없어서 링고게임즈에서 사용하던 접근방법론을 정리해보았다.

사용자 삽입 이미지

2013/12/08 23:38 2013/12/08 23:38
오홍~ =)


2013/12/06 22:44 2013/12/06 22:44
Drawcall 땜시 고생좀 하다가 삽질하면서 알아낸 결과물입니다.

1. Drawcall이란?

화면에 Material을 1개 그리면 1DrawCall이 됩니다.
예를 들어, Mesh1과 Material1을 그리면 Drawcall 1입니다.
Mesh1, Mesh2를 Material1로 그리면 Drawcall 1입니다만, Mesh1은 Material1, Mesh2는 Material2로하면 Drawcall이 2가됩니다.
이는 DirectX든 OpenGL이든 똑같습니다.

* 인터넷에서 퍼온 Drawcall관련 자료입니다.
Mesh는 재각각이지만, Material이 1개이기 때문에 Drawcall 숫자는 1로 찍힙니다.
사용자 삽입 이미지


2. Drawcall이 증가하는게 왜 문제인가?

성능과 직결되는 문제이기 때문입니다. 예를 들어 위의 설명했지만, Mesh 데이터보다 텍스쳐로 사용되는 데이터의 크기가 더 큽니다. 만약 압축이 되어 있다면 압축을 해제해야 하는 문제도 생기겠죠? 암튼, Material을 GPU로 전송하는 수가 작을 수록 더 훌륭한 속도가 보장됩니다.
* PC기준이지만 좋은 자료 : http://www.slideshare.net/egohim/unity ··· imzation

3. 어떻게 해야하나?
자주 호출하는 것보다 VBO같은곳에 모아서 한꺼번에 찍어대면 Drawcall하는 횟수가 줄어서 궁극적으로는 성능이 개선될 수 있습니다. 배치방법은 2가지 방식으로 유니티에서는 지원하더군요.
- Dynamic Batch (움직이거나, 회전하거나, 커지거나, 작아지는!)
  . 300 Tris이하의 오브젝트 (만약에 자식 오브젝트로 등록하더라도... 똑같이 적용됩니다. 무조건 300 Tris)
  . Material을 1개의 Atlas에 다 때려넣어 주세요.
    (추천하는 Plugin은 Atlas 3D : http://u3d.as/content/tracki-studio/at ··· ui%2F5a0 단, NGUI사용자여야 합니다.)
  . Skinned Mesh 또는 실시간 그림자를 받는 녀석은 안됩니다.
- Static Batch (꿈쩍하지 않는녀석)
  . 우측상단에 Staic 체크해두면 알아서 돕니다.



2013/11/08 00:33 2013/11/08 00:33