2017년 12월 20일 수요일

Zenject 의 Inject Binding 방식들 몇가지 메모


// string타입값이 필요할때  생성된 string 인스턴스 "Hello World!" 할당하도록 합니다.
// 적용 대상의 타입은 Greeter로 한정
Container.Bind<string>().FromInstance("Hello World!")
    .When(context => context.ObjectType == typeof(Greeter));

// AsTransient모든 객체 요청이 있을때마다 재활용 없이 인스턴스를 생성하도록 합니다. 
// Inject어트리뷰트에 적용된 아이디가 다음과 같은 경우 > [Inject(Id = "Transient")]
Container.Bind<Dummy>().WithId("Transient").AsTransient();

// AsCached를 사용하는 경우 적용 대상의 타입/조건에 따라 캐쉬된 인스턴스가 사용됩니다.
// When조건이나 WithID조건 있으면 동일한 조건상에서는 같은 인스턴스가 사용됩니다.
// Inject어트리뷰트에 적용된 아이디가 다음과 같은 경우 > [Inject(Id = "Cached")]
Container.Bind<Dummy>().WithId("Cached").AsCached();

// AsSingle는 항상 한개의 인스턴스만 사용합니다.
// AsCached처럼 When조건이나 WithID조건에 따라 다른 인스턴스를 생성하지 않습니다. 싱클톤 패턴에 적합
// Inject어트리뷰트에 적용된 아이디가 다음과 같은 경우 > [Inject(Id = "Single")]
Container.Bind<Dummy>().WithId("Single").AsSingle();


// WithID의 전달 값은 string타입이 일반적이지만 enum을 사용할 수도 있습니다.

/* enum AsScope
   {
      Transient,
      Cached,
      Single,
   }*/
  
Container.Bind<Dummy>().WithId(AsScope.Transient).AsSingle();


// Greeter클래스가 인젝션될  있도록 컨테이너에 바인딩해놓습니다.
// 싱글인스턴스로(AsSingle), 필요할 때가 아닌 즉시 생성(NonLazy)
Container.Bind<Greeter>().AsSingle().NonLazy();

// 초기화 함수가 필요한경우 IInitializable인터페이스를 사용하여 바인딩합니다.
// 값을 인젝션하는 순서는 생성자 > 인젝션 필드 > IInitializable.Initialize 함수순입니다.
Container.Bind<IInitializable>().To<GreeterInit>().AsSingle().NonLazy();

// 앱이 닫힐 때나 장면이 전환될때  객체가 파괴될   정리할 외부 리소스가 존재할 경우 IDisposable를 바인딩 해줄  있다.
Container.Bind<IDisposable>().To<GreeterInit>().AsSingle().NonLazy();


// IWeapon인터페이스에 대한 객체가 필요할때 Weapon클래스 인스턴스를 할당하도록 합니다.
// 적용 대상의 타입은 Player로 한정합니다.
Container.Bind<IWeapon>()
    .To<Weapon>()
    .AsCached()
    .When(context => context.ObjectType == typeof(Player));

// Zenject내에 제공되는 Factory기능을 이용하여 DI형태의 팩토리를 만들  있습니다.
// cubePrefab 프리팹을 기반으로 Cube.Factory클래스를 사용하여 Cube를 생성하도록 합니다.
Container.BindFactory<Cube, Cube.Factory>().FromComponentInNewPrefab(cubePrefab);


// ITickable를 사용하는 InstancingManager클래스에 매프레임 마다 Tick함수를 호출해 주도록 합니다.
// MonoBehaviour의 Update함수 대응
Container.Bind<ITickable>().To<InstancingManager>().AsSingle();

// MonoBehaviour의 FixedUpdate함수 대응
Container.Bind<IFixedTickable>().To<InstancingManager>().AsSingle();

// MonoBehaviour의 LateUpdate함수 대응
Container.Bind<ILateTickable>().To<InstancingManager>().AsSingle();

Container.Bind<InstancingManager>().AsSingle();

2017년 12월 18일 월요일

Mac OS에서 Unity 프로젝트 멀티로 띄우기(Automator활용)


맥에서 유니티 프로그램을 여러개 실행하는 방법

터미널에서 “open –na Unity.app” 명령어 실행



매번 터미널 열기 귀찮으니 Automator를 이용해서 App를 만들고 Dock에 넣어버리자.

Automator 실행 > 새로운 도큐먼트 > 응용프로그램 선택



왼쪽 리스트에서 “쉘 스크립트 실행” 항목 찾아 오른쪽으로 Drag&Drop!

스크립트 내용에 “open –na Unity.app” 입력


파일 > 저장 > 파일명을 정하고(예: UnityMulti.app) 응용프로그램 폴더에 저장
Dock에 넣어두고 편하게 사용하자..

2017년 12월 9일 토요일

Customize Unity (C#)Script Templates


C# 스크립트를 만들면 Unity Editor는 아래 소스 코드를 생성합니다.
(파일명이 클래스의 이름으로 사용됩니다.)


using UnityEngine;
using System.Collections;

public class MyCustomScript : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}


스크립트 템플릿을 변경하려면 아래 경로에 저장된 스크립트 템플릿 파일을 수정해야 합니다.

Windows: C:\Program Files\Unity\Editor\Data\Resources\ScriptTemplates
Mac /Applications/Unity/Unity.app/Contents/Resources/ScriptTemplates


해당 경로에는 아래와 같은 여러개의 템플릿 파일들이 있습니다.

81-C# Script-NewBehaviourScript.cs.txt
83-Shader__Standard Surface Shader-NewSurfaceShader.shader.txt
83-Testing__EditMode Test C# Script-NewEditModeTest.cs.txt
83-Testing__PlayMode Test C# Script-NewPlayModeTest.cs.txt
84-Shader__Unlit Shader-NewUnlitShader.shader.txt
85-Shader__Image Effect Shader-NewImageEffectShader.shader.txt
86-C# Script-NewStateMachineBehaviourScript.cs.txt
86-C# Script-NewSubStateMachineBehaviourScript.cs.txt
87-Playables__Playable Behaviour C# Script-NewPlayableBehaviour.cs.txt
88-Playables__Playable Asset C# Script -NewPlayableAsset.cs.txt
90-Shader__Compute Shader-NewComputeShader.compute.txt


각각의 사용 용도는 아마 파일명에서 대충 유추할 수 있지 않을까 싶습니다.. ^^;

새로 생성되는 C#스크립트 템플릿을 가지고 싶다면 "81-C# Script-NewBehaviourScript.cs.txt" 파일을 편집하면 됩니다.
(일반 편집기로는 권한문제로 저장이 안될 수 있습니다.)

sudo nano "/Applications/Unity/Unity.app/Contents/Resources/ScriptTemplates/81-C# Script-NewBehaviourScript.cs.txt"




템플릿 파일의 기본 형태는 아래와 같이 되어 있을 겁니다.

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

public class #SCRIPTNAME# : MonoBehaviour {

    // Use this for initialization
    void Start () {
        #NOTRIM#
    }

    // Update is called once per frame
    void Update () {
        #NOTRIM#
    }
}


위 소스에서 #SCRIPTNAME#는 파일명을 클래스 명으로 대체하는 부분입니다. 그대로 두는편이 좋겠지요.

#NOTRIM# .. no trim? 정확한 역할이 뭔지 모르겠습니다만~ 아마 공백을 유지하기 위함이 아닐까 생각해봅니다.


아래는 C# 템플릿의 모양을 바꿔본 예제입니다.

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

/**
 * @brief #SCRIPTNAME# Class
 */
public class #SCRIPTNAME# : MonoBehaviour 
{
    #region Public Fields
    #endregion

    #region Unity Methods
    // Use this for initialization
    void Start () 
    {
        #NOTRIM#
    }

    // Update is called once per frame
    void Update () 
    {
        #NOTRIM#
    }
    #endregion

    #region Private Methods
    #endregion
}



템플릿 파일을 수정/저장한 뒤 Unity Editor를 다시 실행하고 새로운 C# 파일을 생성하면 아래와 같이 생성된 소스를 확인할 수 있습니다.

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

/**
 * @brief Test3 Class
 */
public class Test3 : MonoBehaviour 
{
    #region Public Fields
    #endregion

    #region Unity Methods
    // Use this for initialization
    void Start () 
    {

    }

    // Update is called once per frame
    void Update () 
    {

    }
    #endregion

    #region Private Methods
    #endregion
}



* 인식 오류 문제를 위해 원본 템플릿 파일은 백업해 두는것이 좋겠습니다.
* Unity가 업데이트 될 때 수정한 템플릿이 덮어씌어질 수 있겠습니다. 수정한 파일도 백업할 필요가 있겠지요.

2017년 12월 4일 월요일

Unity, Mesh로 Sprite출력하기

Mesh, MeshFilter, MeshRenderer 를 사용한 스프라이트 출력

[출력 화면]

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

// Unity에서는 opengl처럼 GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN을 지원하지 않는듯함.
// 오직. GL_TRIANGLES 삼각형 조합만 지원하는갑다.

[RequireComponent (typeof(MeshRenderer))] 
[RequireComponent (typeof(MeshFilter))] 
public class TestCustomMesh : MonoBehaviour 
{
    // 버텍스 list
    public List<Vector3> listVertex = new List<Vector3>();

    // 색상 정보 list
    public List<Color> listColor = new List<Color>();

    // 정점 인덱스 정보 list
    public List<int> listTriangle = new List<int>();

    // UV 정보 list
    public List<Vector2> listUV = new List<Vector2>();

    // 메쉬
    private Mesh mesh;

    void Start () 
    {
        MeshRenderer meshRenderer = GetComponent<MeshRenderer>(); 
        // 메터리얼 생성
        meshRenderer.material = new Material(Shader.Find("UI/Default"));

        // 메터리얼 설정
        meshRenderer.material.SetColor("_Color", Color.white);
        meshRenderer.material.SetTexture("_MainTex", Resources.Load("Textures/Heart") as Texture);

        // Vertex 정보(색상, UV정보 포함) 적재
        AddVertex(new Vector3(-1, -1, 0), Color.red, new Vector2(0, 0));        ///< 좌하
        AddVertex(new Vector3( 1, -1, 0), Color.white, new Vector2(1, 0));      ///< 우하
        AddVertex(new Vector3(-1,  1, 0), Color.white, new Vector2(0, 1));      ///< 좌상
        AddVertex(new Vector3( 1,  1, 0), Color.white, new Vector2(1, 1));      ///< 우상

        // Triangle 정보 적재
        AddTriangle(0, 2, 1);
        AddTriangle(2, 3, 1);

        // 매쉬 생성
        ApplyMesh();
    }

    // Vertex 정보(색상, UV정보 포함) 적재
    void AddVertex(Vector3 vtVertex, Color color = default(Color), Vector2 vtUV = default(Vector2))
    {
        listVertex.Add(
            new Vector3(
                transform.position.x + vtVertex.x,
                transform.position.y + vtVertex.y,
                transform.position.z + vtVertex.z));

        listColor.Add(color);

        listUV.Add(vtUV);
    }

    // Triangle 정보 적재
    void AddTriangle(int idx1, int idx2, int idx3)
    {
        listTriangle.Add(idx1);
        listTriangle.Add(idx2);
        listTriangle.Add(idx3);
    }

    void ApplyMesh()
    {
        // 메쉬 데이터 새로 생성
        // Mesh mesh = new Mesh(); 

        // MeshFilter로 부터 메쉬 데이터 획득
        Mesh mesh = GetComponent<MeshFilter>().mesh; 
        mesh.Clear();

        // 정점정보와 컬러, 인덱스, UV정보 배열을 셋팅
        mesh.vertices = listVertex.ToArray();
        mesh.colors = listColor.ToArray();
        mesh.triangles = listTriangle.ToArray();
        mesh.uv = listUV.ToArray();

        // 노말 벡터 계산
        mesh.RecalculateNormals();

        // MeshFilter에 저장된 메쉬 데이터를 적재
        
// GetComponent<MeshFilter>().mesh = mesh;
    }
}