보면서 계속영감을 받을수있는..
최고를보고 따라가는.. 슈퍼셀의 그래픽아티스트 (브롤스타즈 credit란에 나옴) 의 포트폴리오.
'공부 > 공부 해 볼 만한것' 카테고리의 다른 글
Unity Fps 샘플예제 (0) | 2019.01.17 |
---|
보면서 계속영감을 받을수있는..
최고를보고 따라가는.. 슈퍼셀의 그래픽아티스트 (브롤스타즈 credit란에 나옴) 의 포트폴리오.
Unity Fps 샘플예제 (0) | 2019.01.17 |
---|
https://github.com/Unity-Technologies/FPSSample
최고의 작업물. (0) | 2019.01.23 |
---|
이벤트를 스트림으로. (asobserabble)
스트림을 구독 (subscripbe)
힙 (0) | 2018.03.25 |
---|---|
3d물체에서 법선벡터가 필요한 이유. (0) | 2016.09.01 |
레퍼런스 카운트 핵심개념 (0) | 2016.08.12 |
<디자인패턴> 명령(command) (0) | 2016.08.05 |
이곳은.. (0) | 2016.08.05 |
-Hello World Example
젠젝트 씬 기본 사용법.
1.하이어라키 Zenject -> Scene Context
2.프로젝트 Create -> Zenject ->MonoInstaller (Ex TestInataller 클래스)
3.2에서 만들어진 스크립트를 게임오브젝트에 달아주고 SceneContext에 연결.
using Zenject; using UnityEngine; using System.Collections; public class TestInstaller : MonoInstaller { public override void InstallBindings() { Container.Bind<string>().FromInstance("Hello World!"); Container.Bind<Greeter>().AsSingle().NonLazy(); } } public class Greeter { public Greeter(string message) { Debug.Log(message); } }
생성자 NonLazy라서 자동으로 호출됨.
SceneContext Monobehavior 은 엔트리 포인트가 됨.
젠젝트가 모든 의존성들을 씬이 시작되기 전에 세팅해줌.
원문 -The SceneContext MonoBehaviour is the entry point of the application, where Zenject sets up all the various dependencies before kicking off your scene. To add content to your Zenject scene, you need to write what is referred to in Zenject as an 'Installer', which declares all the dependencies and their relationships with each other. All dependencies that are marked as "NonLazy" are automatically created after the installers are run, which is why the Greeter class that we added above gets created on startup. If this doesn't make sense to you yet, keep reading!
-Injection
의존성을 주입하는 방법에는 여러가지가 있습니다.
1 - Constructor Injection (생성자를 통한 주입)
public class Foo
{
IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
}
2 - Field Injection (필드를 통한 주입)
public class Foo
{
[Inject]
IBar _bar;
}
-Field Injection은 생성자가 호출된 후에 즉시 호출된다.
[Inject]가 표시된 모든 필드는 컨테이너에서 본인의 의존성을 찾고, 찾은 값이 주입된다.
필드가 private인지 public 인지는 상관 없이 의존성 주입이 실행 된다.
3 - Property Injection (프로퍼티를 통한 주입)
public class Foo
{
[Inject]
public IBar Bar
{
get;
private set;
}
}
Property Injection은 필드 인젝션과 같다. setter은 private,public 둘 다 가능하다.
4 - Method Injection (함수를 통한 주입)
public class Foo
{
IBar _bar;
Qux _qux;
[Inject]
public Init(IBar bar, Qux qux)
{
_bar = bar;
_qux = qux;
}
}
Method Injection은 생성자를 통한 주입과 매우 유사하다.
-함수를 통한 주입은 MonoBehaviours를 활용하는 클래스들에서 추천됩니다. 왜냐하면 MonoBehaviours는 생성자가 없기 때문에!
-추천 사용법
Recommendations
Best practice is to prefer constructor/method injection compared to field/property injection.
-Binding
In Zenject, dependency mapping is done by adding bindings to something called a container. The container should then 'know' how to create all the object instances in your application, by recursively resolving all dependencies for a given object.
젠젝트에서, 의존성 매핑은 컨테이너에 바인딩할 무언가를 더하는 식으로 수행된다.
그것들이 수행되고 나면, 컨테이너는 재귀적으로 주어진 오브젝트들의 의존성을 해소함으로써 오브젝트 객체를 어떻게 만들 것인지를 알게된다,
When the container is asked to construct an instance of a given type, it uses C# reflection to find the list of constructor arguments, and all fields/properties that are marked with an [Inject]
attribute. It then attempts to resolve each of these required dependencies, which it uses to call the constructor and create the new instance.
Each Zenject application therefore must tell the container how to resolve each of these dependencies, which is done via Bind commands.
바인딩 옵션들
ContractType = The type that you are creating a binding for.
ResultType = The type to bind to.
Identifier = The value to use to uniquely identify the binding. This can be ignored in most cases, but can be quite useful in cases where you need to distinguish between multiple bindings with the same contract type. See here for details.
ConstructionMethod = The method by which an instance of ResultType is created/retrieved. See this section for more details on the various construction methods.
Scope = This value determines how often (or if at all) the generated instance is re-used across multiple injections.
Default: AsTransient. Note however that not all bindings have a default, so an exception will be thrown if not supplied. The bindings that do not require the scope to be set explicitly are any binding with a construction method that is a search rather than creating a new object from scratch (eg. FromMethod, FromComponentX, FromResolve, etc.)
It can be one of the following:
In most cases, you will likely want to just use AsSingle, however AsTransient and AsCached have their uses too.
Arguments = A list of objects to use when constructing the new instance of type ResultType. This can be useful as an alternative to adding other bindings for the arguments in the form Container.BindInstance(arg).WhenInjectedInto<ResultType>()
InstantiatedCallback = In some cases it is useful to be able customize an object after it is instantiated. In particular, if using a third party library, it might be necessary to change a few fields on one of its types. For these cases you can pass a method to OnInstantiated that can customize the newly created instance. For example:
Container.Bind<Foo>().AsSingle().OnInstantiated<Foo>(OnFooInstantiated);
void OnFooInstantiated(InjectContext context, Foo foo)
{
foo.Qux = "asdf";
}
Or, equivalently:
Container.Bind<Foo>().AsSingle().OnInstantiated<Foo>((ctx, foo) => foo.Bar = "qux");
Note that you can also bind a custom factory using FromFactory that directly calls Container.InstantiateX before customizing it for the same effect, but OnInstantiated can be easier in some cases
Condition = The condition that must be true for this binding to be chosen. See here for more details.
(Copy|Move)Into(All|Direct)SubContainers = This value can be ignored for 99% of users. It can be used to automatically have the binding inherited by subcontainers. For example, if you have a class Foo and you want a unique instance of Foo to be automatically placed in the container and every subcontainer, then you could add the following binding:
Container.Bind<Foo>().AsSingle().CopyIntoAllSubContainers()
In other words, the result will be equivalent to copying and pasting the Container.Bind<Foo>().AsSingle()
statement into the installer for every sub-container.
Or, if you only wanted Foo in the subcontainers and not the current container:
Container.Bind<Foo>().AsSingle().MoveIntoAllSubContainers()
Or, if you only wanted Foo to be in the immediate child subcontainer, and not the subcontainers of these subcontainers:
Container.Bind<Foo>().AsSingle().MoveIntoDirectSubContainers()
NonLazy = Normally, the ResultType is only ever instantiated when the binding is first used (aka "lazily"). However, when NonLazy is used, ResultType will immediately be created on startup.
IfNotBound = When this is added to a binding and there is already a binding with the given contract type + identifier, then this binding will be skipped.
https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
젠젝트 의존성 주입 (0) | 2018.12.02 |
---|
메모리에서 데이터 스텍 힙 할때의 힙도 있지만.
트리 구조 가운데 힙이라는 것도 있다.
힙은 조금 특이한 형태의 트리(보통 이진 트리)이며,
노드의 각 자식의 값은 노드 자신의 값 이하여야 함( 루트는 그 트리에서 가장 큰 값)
때문에 최대값을 상수시간으로 구하는 것이 가능. (루트가 바로 그것)
검색은 O(n)이고, 이진탐색 트리처럼 주어진 노드 다음으로 큰 노드를 O(log(n))으로 찾는다던지,
O(n)으로 모든 노드를 정렬된 순서로 출력은 불가능.
(최대값을 계속 꺼내주면 정렬된 값을 얻을 수는 있겠지만, 최대값을 빼고 나서 다음 최대값을 찾아서 갱신해줘야 하기 때문에 불가능)
주어진 값들 중에서 빠르게 최대값을 추출해야 한다면 힙을 사용하면 좋다고 함.
책에서 예시를 봤는데 좋은 예시 같아서 기록
병원에서 대기중인 환자들이 있다.
대기중인 환자들 중에는 간단한 상처때문에 온 환자도 있고, 심장마비 때문에 온 환자도 있다. 심장마비 환자에게 더 높은 우선순위를 부여하는 식으로 우선순위를 부여하여 힙에 넣는다. 의사가 다음 환자를 볼때 가장 우선순위가 높은 환자부터 치료를 시작한다. 힙에서 최대값을 꺼내기만 하면 우선순위가 가장 높은 환자를 찾을 수 있으며, 이 연산은 상수시간으로 처리된다.
Unirx 정리 (0) | 2018.12.25 |
---|---|
3d물체에서 법선벡터가 필요한 이유. (0) | 2016.09.01 |
레퍼런스 카운트 핵심개념 (0) | 2016.08.12 |
<디자인패턴> 명령(command) (0) | 2016.08.05 |
이곳은.. (0) | 2016.08.05 |
여기서 파란색 화살표가 법선벡터인데.
법선벡터는 반사각을 계산하기 위해 필요하다.
빛이 저방향으로 들어왔을때 법선벡터를 기준으로 반사각을 계산할수 있다.
법선벡터만 구하면 반사각 계산은 컴퓨터가 해준다....
법선벡터는 삼각형을 이루고 있는 정점 3개만 알고있으면 외적을 통해 계산할수 있다.
Unirx 정리 (0) | 2018.12.25 |
---|---|
힙 (0) | 2018.03.25 |
레퍼런스 카운트 핵심개념 (0) | 2016.08.12 |
<디자인패턴> 명령(command) (0) | 2016.08.05 |
이곳은.. (0) | 2016.08.05 |
http://seorenn.blogspot.kr/2012/06/objective-c.html
프로젝트를 하면서 메모리를 깔끔하게 관리(안쓰는건 해제) 하는것이 굉장이 중요하다는 것과, (몹을 이상한 방법으로 수백마리 만들다가 문제가 생겼었다.)
동적 할당 시 특수장치를 사용하지 않고 전통적인 방법(new delete)으로 할 경우에 주의해야 한다는 것을 깨닫게 되었었다.
(A에서 동적할당 한것을 B에서 해제했는데 A에서 다시참조한다? )
그러던중 레퍼런스 카운트를 사용하는 방법이 있다는 것을 알게 되었는데.
위의 글에 핵심 개념이 잘 정리되어 있다.
Unirx 정리 (0) | 2018.12.25 |
---|---|
힙 (0) | 2018.03.25 |
3d물체에서 법선벡터가 필요한 이유. (0) | 2016.09.01 |
<디자인패턴> 명령(command) (0) | 2016.08.05 |
이곳은.. (0) | 2016.08.05 |
<디자인패턴> 명령(command)
명령 패턴.
GoF의 디자인패턴이라는 책에 나온 정의는
"요청 자체를 캡슐화하는 것입니다. 이를 통해 요청이 서로 다른 사용자를 매개변수로 만들고, 요청을 대기시키거나 로깅하며 ,되돌릴수 있는 연산을 지원합니다."
입니다. 처음봤을때는 무슨소린가 했는데.. 예제와 설명을보면서 내가 이해한 것은 이렇다.
예를들어 게임에서의 버튼을 입력하는 함수가 있다.(전역함수로 KeyDown,jump,Attack,Run이 있다고 가정)
void KeyInput()
{
if(KeyDown('Space')) jump();
else if(KeyDown('Z')) Attack();
else if(KeyDown('X')) Run();
}
이경우에는 특정버튼을 클릭하면 바로 해당 함수가 호출되기 때분에 키를 변경하기가 까다롭다.
(대부분의 게임들에서는 원하는 키로 키변경이 가능하다)
여기서 키변경이 가능하게 하려면, 해당키를 눌렀을때 함수를 바로 호출해 버리지 않고 어떤 절차를 거쳐서 함수가 실행되게 하면 된다.
여기서 어떤 절차를 만드는 것이 명령패턴의 핵심이다.
어떤 절차를 만들기 위해서 명령 클래스를 만든다. (의사코드)
class Command
{
public:
virtual ~Command(){}
virtual void execute() = 0; //순수가상함수
}
그리고 이제 각 행동별 하위 클래스를 만들어준다.
class JumpCommand : public Command()
{
public:
virtual void execute(){jump();}
}
class AttackCommand : public Command()
{
public:
virtual void execute(){Attack();}
}
class RunCommand : public Command()
{
public:
virtual void execute(){Run();}
}
그리고 입력을 관리하는 핸들러 클래스를 만들어주고 각 버튼별로 Command 클래스 포인터를 생성시켜서 필요할때마다 원하는 클래스를 생성후 사용한다.
class InputHandler
{
public:
void handleInput();
~~
private:
Command* ButtonZ;
Command* ButtonX;
Command* ButtonSpace;
}
이제 입력처리를 다음과 같이 한다.
void InputHandler::KeyInput()
{
if(KeyDown('Space')) ButtonSpace->execute();
else if(KeyDown('Z')) ButtonZ->execute();
else if(KeyDown('X')) ButtonX->execute();
}
이로써 할당된 클래스에 따른 execute()함수를 이용하면 특정키에 원하는 명령을 실행할 수 있게 된다.
이것을 다양하게 활용할수 있다.
1. 특정 객체를 인자로 받아서 (예를들어 플레이어,몬스터) 해당 객체에게 원하는 행동을 하게 할 수도 있고.
(객체별로 따로따로 함수를 만들필요가 없음)
2.명령을 한번 할때마다 command객체가 생성되기 때문에 이것을 잘 활용하면 했던 행동 되돌리기 등도 만들수 있다.
특정 행동별로 되돌리기 함수를 만들어놓고 생성된 객체들을 스택에 저장시킨다.
계속 명령을 실행하다 보면 다음과 같이 스택이 쌓이게 된다
(명령1) (명령2) (명령3) (명령4) 오래된 것들은 지우고 최신것들을 보관하고있다가 실행취소하면 현재명령의 되돌리기 함수를 통해 했던 명령을 취소하면 된다.
이것을 또 활용해서 명령들을 저장해두고 있다가 처음부터 순서대로 실행하면 다시보기도 만들 수 있을것 같다.
-참고: 책 게임프로그래밍 패턴
Unirx 정리 (0) | 2018.12.25 |
---|---|
힙 (0) | 2018.03.25 |
3d물체에서 법선벡터가 필요한 이유. (0) | 2016.09.01 |
레퍼런스 카운트 핵심개념 (0) | 2016.08.12 |
이곳은.. (0) | 2016.08.05 |
이곳은 시간날때마다 짬짬이 공부한 내용을 기록해두기 위한 공간입니다.
제가 이해한것 위주로 올릴것이기 떄문에 제 생각이 틀릴수도 있습니다.
틀린 내용은 바로 지적해주시면 감사하겠습니다.
Unirx 정리 (0) | 2018.12.25 |
---|---|
힙 (0) | 2018.03.25 |
3d물체에서 법선벡터가 필요한 이유. (0) | 2016.09.01 |
레퍼런스 카운트 핵심개념 (0) | 2016.08.12 |
<디자인패턴> 명령(command) (0) | 2016.08.05 |