'Unity'에 해당되는 글 17건

  1. 2019.05.09 Animator 이용법 자습
  2. 2019.05.03 Tower Defense Template
  3. 2019.05.02 Shooting Tutorial 자습서 분해하고 재구성하기
  4. 2019.05.02 GitHub
  5. 2019.04.25 Raycast, Collider, Rigidbody, Joystick 이용 캐릭터 이동하기
  6. 2019.04.19 3D와 랜더링 파이프라인
  7. 2019.04.16 씬 전환 및 가서 공격하기
  8. 2019.04.16 왔다갔다 때리기

Animator 이용법 자습

Unity/Study 2019. 5. 9. 16:19

Animator에는 크게 State와 Transition으로 이루어진다.

State는 상태, Transition은 State와 State를 이어주는 전이로서, Transition에 있는 Conditions라는 조건을 통해

다른 State로 Animation을 전환할 수 있게 해준다.

즉, 위의 사진을 예시로 했을 때, Conditions에 isJump라는 Parameter가 조건으로 있으므로, isJump가 참이 되면

fox_idle이라는 state에서 fox_jump라는 state로 변화하게 되는 것이다.



Animator.Play를 이용한 Animation 재생



Animator의 Trigger Parameter를 이용한 Animation 재생



Animator의 Bool Parameter를 이용한 Animation 재생



Float형 Parameter를 이용하여 Animation의 Speed를 조절하기

 

Inspector 창에서 Multiplier항에 Parameter를 체크하고 지정해주면,

해당 Parameter의 값을 기준으로 해당 항목의 값이 변화한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
 
public class TestAnim : MonoBehaviour
{
    public Animator anim;
    public Button[] btn;
 
    private void Awake()
    {
        this.anim = this.gameObject.GetComponentInChildren<Animator>();
    }
 
    private void Start()
    {
        this.ControlAnimation();
    }
 
    private void ControlAnimation()
    {
        this.btn[0].onClick.AddListener(() =>
        {
            StartCoroutine(this.PlayAnimation("fox_idle"));
        });
        this.btn[1].onClick.AddListener(() =>
        {
            StartCoroutine(this.PlayAnimation("fox_run"));
        });
        this.btn[2].onClick.AddListener(() =>
        {
            StartCoroutine(this.PlayAnimation("fox_jump"));
        });
        this.btn[3].onClick.AddListener(() =>
        {
            StartCoroutine(this.PlayAnimation("fox_hurt"));
        });
        this.btn[4].onClick.AddListener(() =>
        {
            StartCoroutine(this.PlayAnimation("fox_crouch"));
        });
        this.btn[5].onClick.AddListener(() =>
        {
            StartCoroutine(this.PlayAnimation("fox_climb"));
        });
    }
 
    private IEnumerator PlayAnimation(string animName)
    {
        this.anim.Play(animName);
        yield return new WaitForSeconds(this.anim.GetCurrentAnimatorStateInfo(0).length);
        yield return new WaitForSeconds(2.0f);
        this.anim.SetFloat("AnimationSpeed"2.0f);
        yield return new WaitForSeconds(2.0f);
        this.anim.SetFloat("AnimationSpeed"3.0f);
        yield return new WaitForSeconds(2.0f);
        this.anim.SetFloat("AnimationSpeed"5.0f);
 
    }
}
 
cs


'Unity > Study' 카테고리의 다른 글

testgpgs개인정보  (0) 2019.06.13
GitHub  (0) 2019.05.02
3D와 랜더링 파이프라인  (0) 2019.04.19
:

Tower Defense Template

Unity/Unity Tutorial 2019. 5. 3. 17:58

유니티 자습서에 있는 Tower Defense Template를 분해하여 나만의 코드로 다시 재구현 해보았다.

구현한 부분은 길 만들기(Navmesh), 적군 오브젝트 생성(Object Pool이용), 노드 단위로 이동(Collider이용), 도착시 일정시간 후 비활성화 및 재활용이다.

느낀점 : Tutorial 맞나싶다.


//분석

카메라 컨트롤

  - 바운더리의 마우스 위치에 따라 카메라 이동

  - 마우스 중간휠로 줌인/줌아웃

타워선택

- 스냅

- 건설 불가 지역에는 빨간색 표시

- 타워에 원 생성 (Radius Visualiser?)

- 건설 가능 위치에서 타워 로테이션

- 우클릭시 선택된 타워 설치 취소

타워설치

- 애니메이션 실행

- 원이 사라짐

- 타워 설치 된 곳 (바닥)에 색이 칠해짐(mesh)

적기생성

- 오브젝트 풀링(PoolManager)

- 풀링 후 오브젝트를 꺼내지 않는다.

지형

- Navmesh 사용

- Areas : (Flyable)

- Level04_Pt{n}_Road 여러개에 Navmesh적용

Hoverbuggy

- Navmesh Agent

- Capsule Collider

- Rigid Body (Is Kinematic Active)

- Targetter.cs, TargetterEditor.cs (target collider를 editor에서 표시)

- 이동 : Agent.cs, MoveToNode() method 실행, 한번에 목표지점으로 이동이 아닌 노드 단위로 나누어 이동

Node(Node.cs)

- MonoBehaviour

- NodeEditor.cs => Inspector Customizing

- Level1Configuration/Nodes/{n}


//계획

1. new project

2. 바닥에 mesh(navmesh 적용)

3. 시작위치, 끝 위치 설정

4. 버튼 생성

5. 버튼 누를 시 적군 생성하여 시작위치부터 끝 위치까지 navmesh통하여 이동하는지 확인

6. 노드 제작

7. 노드 단위로 이동하게끔 변경


//코드읽고 생각을 정리한 것

Node

AreaMeshCreator Type 이용하여 area에 Mesh를 지정하는 탭을 생성

NodeSelector를 이용하여 다음 Node를 리턴한다.

GetRandomPointInNodeArea : Node의 MeshCreator를 이용하여 영역 내 랜덤 위치값을 찾아 리턴함

OnTriggerEnter를 이용하여 다른 gameObject의 Agent가 node의 area에 enter할 때, 현재 노드를 기준으로 다음 노드를 가져옴.

OnValidate Method에서 Collider가 있으면 isTrigger를 활성화하고, AreaMeshCreator가 null일 경우 자식에게서 찾는다.

OnDrawGizmos를 통해 노드 상단에 이미지를 가지고 기즈모로 출력함.

Vector3.up = Vector3(0,1,0)

NodeSelector

linkedNodes라는 List에 Node들을 저장하고 NodeSelector를 통해 노드를 선택한다.

GetNextNode()를 이용하여 리스트에서 다음 노드를 찾아 리턴하고, 다음 노드가 null일 경우 endPoint를 리턴한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class Level01 : MonoBehaviour
{
    public Button btn;
    public GameObject objPool;
    public GameObject startPosition, endPosition;
 
    private Level01_ObjectPool pool;
    private int idx;
    
    void Start()
    {
        this.pool = this.objPool.GetComponent<Level01_ObjectPool>();
        this.btn.onClick.AddListener(() =>
        {
            this.CreateEnemy();
        });    
    }
 
    private void CreateEnemy()
    {
        var list = this.pool.listEnemy;
        if(this.idx == list.Length - 1)
        {
            this.idx = 0;
        }
        for(; this.idx < list.Length; idx++)
        {
            if (list[this.idx].gameObject.activeSelf == false)
            {
                list[this.idx].transform.position = startPosition.transform.position;
                list[this.idx].SetActive(true);
                list[this.idx].GetComponent<Level01_Enemy>().Move(this.startPosition.GetComponent<TestNode>().GetNextNode().transform.position);
                break;
            }
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestNode : MonoBehaviour
{
    public TestNode GetNextNode()
    {
        var selector = this.gameObject.GetComponent<TestNodeSelector>();
        if(selector != null)
        {
            return selector.GetNextNode();
        }
        return null;
    }
 
    public void OnTriggerEnter(Collider other)
    {
        var agent = other.gameObject.GetComponent<Level01_Enemy>();
        if(agent != null)
        {
            if(this.gameObject.name == "End")
            {
                StartCoroutine(this.WaitForSeconds(() =>
                {
                    agent.gameObject.SetActive(false);
                    StopAllCoroutines();
                }));
            }
            else
            {
                var coordinate = this.GetNextNode().transform.position;
                agent.Move(coordinate);
                Debug.Log("다음 node coordinate 전달완료");
            }
        }
    }
 
    private IEnumerator WaitForSeconds(System.Action OnCompleteWait)
    {
        yield return new WaitForSeconds(1.0f);
        OnCompleteWait();
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
 
public class Level01_Enemy : MonoBehaviour
{
    public void Move(Vector3 target)
    {
        NavMeshAgent agent = this.GetComponent<NavMeshAgent>();
        agent.enabled = false;
        if(this.gameObject.activeSelf == true)
        {
            agent.enabled = true;
            agent.destination = target;
        }        
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class Level01 : MonoBehaviour
{
    public Button btn;
    public GameObject objPool;
    public GameObject startPosition, endPosition;
 
    private Level01_ObjectPool pool;
    private int idx;
    
    void Start()
    {
        this.pool = this.objPool.GetComponent<Level01_ObjectPool>();
        this.btn.onClick.AddListener(() =>
        {
            this.CreateEnemy();
        });    
    }
 
    private void CreateEnemy()
    {
        var list = this.pool.listEnemy;
        if(this.idx == list.Length - 1)
        {
            this.idx = 0;
        }
        for(; this.idx < list.Length; idx++)
        {
            if (list[this.idx].gameObject.activeSelf == false)
            {
                list[this.idx].transform.position = startPosition.transform.position;
                list[this.idx].SetActive(true);
                list[this.idx].GetComponent<Level01_Enemy>().Move(this.startPosition.GetComponent<TestNode>().GetNextNode().transform.position);
                break;
            }
        }
    }
}
 
cs


'Unity > Unity Tutorial' 카테고리의 다른 글

Shooting Tutorial 자습서 분해하고 재구성하기  (0) 2019.05.02
:

Shooting Tutorial 자습서 분해하고 재구성하기

Unity/Unity Tutorial 2019. 5. 2. 18:49


자습서 중 하나인 Space Shooter Tutorial의 코드를 공부하고 처음부터 나만의 코드로 다시 재구성 해보았다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestShootingGame : MonoBehaviour
{
    public Transform[] arrGround;
    public GameObject[] meteors;
    public GameObject spaceShip;
    public GameObject objPool;
    public Vector3 spawnPosition;
    public float xMin, xMax, zMin, zMax;
    public float tilt;
    public float waveDelay, spawnDelay, meteorCount;
    private Rigidbody shipBody;
    private float speed = 5.0f;
    private int index = 0;
 
    // Start is called before the first frame update
    void Start()
    {
        this.shipBody = this.spaceShip.GetComponent<Rigidbody>();
    }
 
    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < this.arrGround.Length; i++)
        {
            this.arrGround[i].Translate(new Vector3(0-0.1f, 0* this.speed);
            if (this.arrGround[i].transform.localPosition.z <= -30)
            {
                this.arrGround[i].transform.localPosition = new Vector3(00, 60f);
            }
        }
        if(Input.GetMouseButtonDown(0))
        {
            var list = this.objPool.GetComponent<TestObjectPool>().listObj;
            print(list.Count);
            foreach(var bullet in list)
            {
                if(bullet.activeSelf == false)
                {
                    bullet.SetActive(true);
                    bullet.gameObject.GetComponent<TestBullets>().Init();
                    bullet.transform.position = GameObject.Find("bulletStartPoint").transform.position;
                    break;
                }
            }
        }
        this.Move();
        StartCoroutine(this.CreateWave());
    }
 
    private IEnumerator CreateWave()
    {
        yield return new WaitForSeconds(2.0f);
        while (true)
        {
            for (int i = 0; i < this.meteorCount; i++)
            {
                GameObject meteor = this.meteors[Random.Range(0, meteors.Length)];
                if(meteor.activeSelf == false)
                {
                    meteor.SetActive(true);
                    meteor.transform.GetComponent<TestMeteor>().Init();
                    meteor.transform.position = new Vector3(Random.Range(-this.spawnPosition.x, this.spawnPosition.x), this.spawnPosition.y, this.spawnPosition.z);
                    meteor.transform.rotation = Quaternion.identity;
                }
                yield return new WaitForSeconds(this.spawnDelay);
            }
        }
    }
 
    private void Move()
    {
        //Horizaontal = 수평, Virtical = 수직 (-1 ~ 1 return)
        float horizontal = Input.GetAxis("Horizontal");
        float virtical = Input.GetAxis("Vertical");
 
        var movement = new Vector3(horizontal, 0, virtical);
        this.shipBody.velocity = movement * this.speed;
 
        this.shipBody.position = new Vector3(Mathf.Clamp(this.shipBody.position.x, this.xMin, this.xMax),
                                             0, Mathf.Clamp(this.shipBody.position.z, this.zMin, this.zMax));
        this.shipBody.rotation = Quaternion.Euler(00this.shipBody.velocity.x * -this.tilt);
 
    }
}
 
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestBGScroller : MonoBehaviour
{
    public Transform[] ground;
    public float speed = 2.0f;
 
    private void Update()
    {
        for (int i = 0; i<this.ground.Length; i++)
        {
            this.ground[i].Translate(new Vector3(0-0.1f, 0* this.speed);
            if(this.ground[i].transform.localPosition.z <= -30)
            {
                this.ground[i].transform.localPosition = new Vector3(00, 60f);
            }
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestObjectPool : MonoBehaviour
{
    public List<GameObject> listObj;
}
 
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestMeteor : MonoBehaviour
{
    public float tumble;
    public float speed;
    public GameObject particle;
    private ParticleSystem fx;
 
    void Start()
    {
        this.fx = this.particle.GetComponentInChildren<ParticleSystem>();
        GetComponent<Rigidbody>().angularVelocity = Random.insideUnitSphere * this.tumble;
        GetComponent<Rigidbody>().velocity = transform.forward * this.speed;
    }
 
    public void Init()
    {
        StartCoroutine(this.CountDownToPassive());
    }
 
    private IEnumerator CountDownToPassive()
    {
        while(true)
        {
            if(this.transform.position.z < -14)
            {
                this.gameObject.SetActive(false);
                break;
            }
            yield return null;
        }
        
        //Debug.Log("countdonwtopassive");
        //yield return new WaitForSeconds(2.0f);
        //this.gameObject.SetActive(false);
        //yield return null;
    }
 
    private void OnTriggerEnter(Collider other)
    {
        if(!other.CompareTag("Enemy"))
        {
            this.gameObject.SetActive(false);
            this.fx.gameObject.SetActive(true);
            this.fx.transform.position = this.gameObject.transform.position;
            this.fx.Play();
        }
    }
}
 
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestBullets : MonoBehaviour
{
    public float speed;
 
    void Start()
    {
        GetComponent<Rigidbody>().velocity = transform.forward * speed;
    }
 
    public void Init()
    {
        StartCoroutine(this.TimeToOff());
    }
 
    private void OnTriggerEnter(Collider other)
    {
        this.gameObject.SetActive(false);
    }
 
    private IEnumerator TimeToOff()
    {
        yield return new WaitForSeconds(1.0f);
        this.gameObject.SetActive(false);
    }
}
 
cs


'Unity > Unity Tutorial' 카테고리의 다른 글

Tower Defense Template  (0) 2019.05.03
:

GitHub

Unity/Study 2019. 5. 2. 18:18

git?

VCS(Version Control System) 중 하나인 DVCS(Distributed Version Control System)

Working Directory    ->    Index    ->    HEAD

         *add*   *commit*

add를 통해 Index에 추가를하고 commit을 통해 확정

commit하면 HEAD에는 반영됐으나 서버에는 변동X

push를 통하여 HEAD에서 바뀐 값을 서버로 전송

branch(가지치기)

- 격리된 상태에서 개발하기 위함

- 완료 후에 본래의 가지로 돌아와서 병합(merge)

- checkout을 통해 새로운 가지를 만들고,

  새로운 가지에서 작업을 한다.

  완료 후 서버 저장소에 전송하면 타인도 접근가능

merge(갱신과 병합)

- 서버 저장소와 같은 값으로 갱신시 pull이용

- pull 사용시, 서버 저장소의 변경된 값이 로컬에 fetch하고 merge된다.

//merge <가지 이름>으로 가지치기한 가지도 병합이가능

//conflict(충돌)이 일어나는 경우, 해결 후 병합을 하면 됨.

//손머지, 선택 등 머지에는 방법이 많다.

//손머지 같은 경우 손으로 소스코드를 수정하고 bash에서 add를 통하여 추적하게 하고,

//다시 commit을 하면 정상적으로 진행이 된다.

//pull은 서버 저장소의 소스를 로컬로 가져오면서 현재 작업중인 소스들의 merge까지 통합실행

//fetch는 서버 저장소의 소르르 로컬로 가져오기만하고 merge하지않음

'Unity > Study' 카테고리의 다른 글

testgpgs개인정보  (0) 2019.06.13
Animator 이용법 자습  (0) 2019.05.09
3D와 랜더링 파이프라인  (0) 2019.04.19
:

Raycast, Collider, Rigidbody, Joystick 이용 캐릭터 이동하기

Unity/수업내용 2019. 4. 25. 18:11

Joystick 이용하여 이동하기



Keyboard(W,A,S,D) 이용하여 이동하기



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class TestRaycastAndCollider : MonoBehaviour
{
    public Text txtMousePoint;
    public Text txtHitPoint;
    public GameObject heroGo;
    private Animator heroAnim;
    private Coroutine heroRoutine;
    private Coroutine joystickRoutine;
 
    public TestMyJoystick joystick;
 
    private void Awake()
    {
        Debug.Log("TestRaycastAndCollider Awake!");
    }
 
    // Start is called before the first frame update
    void Start()
    {
        this.heroAnim = heroGo.GetComponent<Animator>();
        Debug.Log("TestRaycastAndCollider Start!");
 
        this.joystick.OnPointerDownHandler = () =>
        {
            Debug.Log("다운핸들러");
            if (this.joystickRoutine != null)
            {
                StopCoroutine(this.joystickRoutine);
            }
            StartCoroutine(this.UpdateJoystickImpl());
        };
        this.joystick.OnPointerUpHandler = () =>
        {
            Debug.Log("업핸들러");
            StopAllCoroutines();
            this.heroAnim.Play("idle");
        };
    }
 
    private void UpdateJoystick()
    {
        Vector3 direction = Vector3.forward * this.joystick.Vertical + Vector3.right * joystick.Horizontal;
 
        direction = new Vector3(direction.x, 0, direction.z).normalized;
        if (direction != Vector3.zero)
        {
            this.heroAnim.Play("run");
            this.heroGo.transform.position += direction * 1.0f * Time.deltaTime;
 
            var rad = Mathf.Atan2(direction.x, direction.z);
            var dig = Mathf.Rad2Deg * rad;
            this.heroGo.transform.rotation = Quaternion.LookRotation(direction);
            //this.heroGo.transform.rotation = Quaternion.Euler(new Vector3(0, dig, 0));
 
        }
        else
        {
            this.heroAnim.Play("idle");
        }
    }
 
    private IEnumerator UpdateJoystickImpl()
    {
        while (true)
        {
            Vector3 direction = (Vector3.forward * this.joystick.Vertical + Vector3.right * joystick.Horizontal).normalized;
            if (direction != Vector3.zero)
            {
                this.heroGo.transform.rotation = Quaternion.LookRotation(direction);
                this.heroAnim.Play("run");
                this.heroGo.transform.position += direction * 2.0f * Time.deltaTime;
                yield return null;
            }
            else
            {
                this.heroAnim.Play("idle");
            }
        }
    }
 
    // Update is called once per frame
    private void UpdateKeyInput()
    {
        var keyY = Input.GetAxis("Vertical");
        var keyX = Input.GetAxis("Horizontal");
        Debug.LogFormat("keyY : {0}, keyX : {1}", keyY, keyX);
 
        var moveKey = new Vector3(keyX, 0, keyY).normalized;
        if (moveKey != Vector3.zero)
        {
            this.heroAnim.Play("run");
            this.heroGo.transform.position += moveKey * 1.0f * Time.deltaTime;
            var rad = Mathf.Atan2(keyX, keyY);
            var dig = Mathf.Rad2Deg * rad;
            this.heroGo.transform.rotation = Quaternion.Euler(new Vector3(0, dig, 0));
 
        }
        else
        {
            this.heroAnim.Play("idle");
        }
    }
 
    private void UpdateMouseInput()
    {
        if(Input.GetMouseButton(0))
        {
            //찍은 곳 스크린 좌표 표시
            this.txtMousePoint.text = Input.mousePosition.ToString();
 
            //찍은 곳 Ray생성
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
 
            //화면 Ray표시
            Debug.DrawRay(ray.origin, ray.direction * 1000, Color.red, 5f);
 
            RaycastHit hitInfo;
            if(Physics.Raycast(ray.origin, ray.direction, out hitInfo, 1000))
            {
                Debug.LogFormat("hitInfo.point : {0}", hitInfo.point.ToString());
                this.txtHitPoint.text = hitInfo.point.ToString();
                this.Move(hitInfo.point);
            }
            else
            {
                this.txtHitPoint.text = "None";
            }
        }
    }
 
    public void Move(Vector3 targetCoordinate)
    {
        if(this.heroRoutine == null)
        {
            this.heroAnim.Play("run");
        }
        if(this.heroRoutine != null)
        {
            StopAllCoroutines();
        }
        this.heroRoutine = StartCoroutine(this.MoveHero(targetCoordinate, () =>
        {
            this.heroAnim.Play("idle");
        }));
    }
 
    private IEnumerator MoveHero(Vector3 targetCoordinate, System.Action OnCompleteMove)
    {
        this.heroGo.transform.LookAt(targetCoordinate);
        var dir = (targetCoordinate - this.heroGo.transform.position).normalized;
        var speed = dir * 1.0f * Time.deltaTime;
        while(true)
        {
            var distance = Vector3.Distance(targetCoordinate, this.heroGo.transform.position);
            this.heroGo.transform.position += speed;
            if(distance <= 0.01f)
            {
                this.heroGo.transform.position = targetCoordinate;
                break;
            }
            yield return null;
        }
        OnCompleteMove();
    }
}
 
cs


'Unity > 수업내용' 카테고리의 다른 글

Scroll View 동적생성  (0) 2019.05.28
UGUI를 이용해 Scroll View UI 만들기  (0) 2019.05.24
:

3D와 랜더링 파이프라인

Unity/Study 2019. 4. 19. 01:49

1프레임은 1장의 이미지와 같다.

PC는 3D모델을 재생하는데에 수 많은 연산을 통해 2D 이미지를 연속적으로 재생한다.


unity에서 부르는 scene은 object들의 모음으로서, 이 object들은 Polygon(다각형)이고, 이는 Vertex(꼭지점)으로 이루어진다.

내가 현재 공부하면서 사용하는 모델을 보면 모두 Polygon으로 이루어져 있다.


또한 카메라라고 부르는 object는 우리가 모니터를 통해 게임을 플레이할때 랜더링을 하여 출력할 이미지의 범위(?)를 지정하는 것이다.

카메라가 비추는 부분을 랜더링 파이프라인을 통하여 2D 이미지로 변환하여 모니터에 출력해주는 것이다.


카메라가 비추고 있는 부분, 즉 출력할 장면을 하나의 3차원 이미지라고 하자.

그럼 이 3차원 이미지는 여러개의 Polygon으로 이루어져 있고, 이 Polygon들은 Vertex로 이루어져 있다.

이 3차원 이미지의 Vertex들을 모아 Vertex Shader(정점 셰이더)로 보낸다.

Vertex Shader에서는 변환 과정을 맡는다. 

각각의 Polygon들은 각각의 공간(Local Space)에서 자신만의 좌표(Coordinate)를 가지고 있는데, 이 Polygon들을 하나의 공간(Space)에 모은다.

//unity에서 쓰는 local position 값을 world position으로 바꾼다고 생각하면 편할 것 같다.

후에 우리가 출력을 원하는 곳을 가리키는 카메라가 보고 있는 공간(View Space)으로 Polygon들이 위치한다.

사용하는 카메라라는 개념은 현실과 다르기때문에 일정한 구역까지만 표현한다. //게임에서 시야거리 조절하듯이


위처럼 카메라가 위치해 있는 곳 부터 far plane까지만 표현하는 것이다. 위 그림에서 파란 공간을 view volume이라 한다.

후에 원근법을 이용하여 표현하기 위해 Clipping Space로 변환한다. (3차원 -> 3차원)


그 다음 레스터화(resterize)를 한다.

Clipping Space로 변환하고 나면 선에 걸치거나 육면체 바깥으로 벗어난 Polygon들이 있을텐데 이 부분들을 잘라낸다.

이를 Clipping이라 한다.

다음으로 원근 나눗셈이라는 것을 통하여 3차원을 2차원으로 변환한다. (z좌표로 모든 성분을 나누어 3차원 개념을 지움)

그 다음 보이지 않는 Polygon, 즉 필요가 없는 Polygon들을 제거한다.(back-face culling)

그리고 2차원으로 변환된 이미지가 출력될 뷰포트(스크린상의 공간)으로 이전하기 위해 윈도우 좌표로 변환한다.

마지막으로 픽셀 위치, 컬러 등 각 Vertex간 속성을 할당한다.


마지막으로 생성된 pixel들에 조명, 텍스쳐 등 작업을 거쳐 색칠하는 단계를 거친다. (이를 프래그먼트 처리 단계라고 함)




※공부하는 중이기 때문에 사실과는 다를 수 있음

※내가 이해한 내용을 작성하였기 때문에 난잡함

※랜더링 파이프라인은 고정 기능 파이프라인, 프로그래머블 파이프라인이 있다. (Unity에서는 Scriptable Render Pipeline이 있음)

  //https://www.youtube.com/watch?v=eJEwnI8UGe4 (Scriptable Render Pipeline: 알아두어야 하는 사항들 (Unity Korea))

  //https://www.youtube.com/watch?v=zbjkEQMEShM (Unity at GDC - Scriptable Render Pipeline Intro & Lightweight Rendering Pipeline (Unity))





How Rendering Graphics Works in Games! (TheHappieCat)

https://www.youtube.com/watch?v=cvcAjgMUPUA


Game Graphics Pipeline Explained by Tom Petersen of nVidia (Gamers Nexus)

https://www.youtube.com/watch?v=4gyP94hsC14


Understanding the Graphics Pipeline (Oscar Chavez)

https://www.youtube.com/watch?v=0PTBOX1HHIo


Graphics Pipeline 3D Rendering (LearnEveryone)

https://www.youtube.com/watch?v=BUcch9b6cFg


21 - Rendering Pipeline (Shaderdev.com) (Chayan Vinayak)

https://www.youtube.com/watch?v=qHpKfrkpt4c

'Unity > Study' 카테고리의 다른 글

testgpgs개인정보  (0) 2019.06.13
Animator 이용법 자습  (0) 2019.05.09
GitHub  (0) 2019.05.02
:

씬 전환 및 가서 공격하기

Unity/과제 2019. 4. 16. 18:57

App카메라 유지, 코루틴, Json, 익명함수, 이벤트 이용

App->Logo->Title(데이터로딩)->InGame 순으로 씬전환

#문법 공부 많이 해야함




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
namespace minseok
{
    public partial class App : MonoBehaviour
    {
        public Camera uiCamera;
 
        //인스턴스화 될때
        private void Awake()
        {
            var oper = SceneManager.LoadSceneAsync("Logo");
            oper.completed += (asyncOper) =>
            {
                Debug.Log("logo scene 로드 완료");
                var logo = GameObject.FindObjectOfType<Logo>();
                logo.Init(this.uiCamera);
            };
            DontDestroyOnLoad(this);
        }
    }
}
 
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
namespace minseok
{
    public class Logo : MonoBehaviour
    {
        public UILogo uiLogo;
 
        public void Init(Camera uiCamera)
        {
            this.uiLogo.onFadeInComplete = () =>
            {
                var oper = SceneManager.LoadSceneAsync("Title");
                oper.completed += (asyncOper) =>
                {
                    Debug.Log("Title scene 로드 완료");
                    var title = GameObject.FindObjectOfType<Title>();
                    title.Init(uiCamera);
                };
                Debug.Log("fade in 완료");
                StopAllCoroutines();
            };
            
            this.uiLogo.onFadeOutComplete = () =>
            {
                Debug.Log("fade out 완료");
                //3초 후 실행
                StartCoroutine(this.WaitForSecond(3, () =>
                {
                    StartCoroutine(this.uiLogo.FadeIn());               
                }));
            };
 
            this.uiLogo.Init(uiCamera);
            StartCoroutine(this.uiLogo.FadeOut()); //1실행
        }
 
        private IEnumerator WaitForSecond(float sec, System.Action onCompleteWait)
        {
            yield return new WaitForSeconds(sec);
            onCompleteWait();
        }
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Newtonsoft.Json;
 
namespace minseok
{
    public class Title : MonoBehaviour
    {
        public UITitle uiTitle;
        public Button btn;
 
        private void Awake()
        {
            this.btn.onClick.AddListener(() =>
            {
                var oper = SceneManager.LoadSceneAsync("InGame");
                oper.completed += (asyncOperation) =>
                {
                    Debug.Log("InGame 씬 로드완료");
                };
            });
        }
 
        public void Init(Camera uiCamera)
        {
            this.DataLoad();
 
            this.uiTitle.onFadeOutComplete = () =>
            {
                Debug.Log("title의 fade in 완료");
                StopCoroutine(this.uiTitle.FadeOut());
            };
 
            this.uiTitle.Init(uiCamera);
            StartCoroutine(this.uiTitle.FadeOut());
        }
 
        private IEnumerator WaitForSecond(float sec, System.Action onCompleteWait)
        {
            yield return new WaitForSeconds(sec);
            onCompleteWait();
        }
 
        private void DataLoad()
        {
            var data = DataManager.GetInstance();
            var textAsset = Resources.Load<TextAsset>("Data/character_data");
            var json = textAsset.text;
            var dataJson = JsonConvert.DeserializeObject<CharacterData[]>(json);
            foreach(var datas in dataJson)
            {
                data.dicCharacterData.Add(datas.id, datas);
            }
 
            textAsset = Resources.Load<TextAsset>("Data/character_anim_data");
            json = textAsset.text;
            var animJson = JsonConvert.DeserializeObject<CharacterAnimData[]>(json);
            foreach(var datas in animJson)
            {
                data.dicCharacterAnim.Add(datas.id, datas);
            }
        }
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class InGame : MonoBehaviour
    {
        private Character hero;
        private Character monster;
        private System.Action onCompleteAttack;
 
        private void Start()
        {
            this.hero = this.CreateCharacter(0);
            this.monster = this.CreateCharacter(1);
            this.StartGame();
        }
 
        private void StartGame()
        {
            this.hero.transform.LookAt(this.monster.transform);
            this.monster.transform.LookAt(this.hero.transform);
            this.hero.Move(this.monster, () =>
            {
                this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnim[this.hero.info.id].idle_anim_name);
                this.hero.Attack(this.monster, this.onCompleteAttack);
            });
            this.onCompleteAttack = () =>
            {
                if(this.monster.info.hp > 0)
                {
                    this.hero.Attack(this.monster, this.onCompleteAttack);
                }
                else
                {
                    Debug.LogFormat("{0}를 처치했습니다!", DataManager.GetInstance().dicCharacterData[this.monster.info.id].name);
                    this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnim[this.hero.info.id].idle_anim_name);
                }
            };
        }
 
        private Character CreateCharacter(int id)
        {
            var data = DataManager.GetInstance();
            var charPrefab = Resources.Load<GameObject>("Prefabs/Character");
            var charGo = GameObject.Instantiate<GameObject>(charPrefab);
            var modelPrefab = Resources.Load<GameObject>(data.dicCharacterData[id].prefab_name);
            var modelGo = GameObject.Instantiate<GameObject>(modelPrefab);
            var character = charGo.AddComponent<Character>();
            
            character.Model = modelGo;
            character.name = data.dicCharacterData[id].name;
            character.info = new CharacterInfo(id, data.dicCharacterData[id].hp, new Vector3(000));
 
            if(character.info.id == 1)
            {
                character.transform.position = new Vector3(505);
            }
            else
            {
                character.transform.position = character.info.position;
            }
 
            Debug.Log("캐릭터가 생성되었습니다.");
            return character;
        }
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class DataManager
    {
        private static DataManager instance;
        public Dictionary<int, CharacterData> dicCharacterData = new Dictionary<int, CharacterData>();
        public Dictionary<int, CharacterAnimData> dicCharacterAnim = new Dictionary<int, CharacterAnimData>();
 
        private DataManager()
        {
 
        }
 
        public static DataManager GetInstance()
        {
            if(DataManager.instance == null)
            {
                DataManager.instance = new DataManager();
            }
            return DataManager.instance;
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
namespace minseok
{
    public class UIBase : MonoBehaviour
    {
        public Canvas canvas;
        public Image dim;
        public System.Action onFadeOutComplete;
        public System.Action onFadeInComplete;
 
        public virtual void Init(Camera uiCamera)
        {
            this.canvas.worldCamera = uiCamera;
        }
 
        public IEnumerator FadeOut()
        {
            var color = this.dim.color;
            color.a = 1;
            this.dim.color = color;
 
            float alpha = color.a;
            while (true)
            {
                alpha -= 0.016f;
                color.a = alpha;
                this.dim.color = color;
                if (alpha <= 0)
                {
                    alpha = 0f;
                    break;
                }
                yield return null;
            }
            this.onFadeOutComplete();
        }
 
        public IEnumerator FadeIn()
        {
            Debug.Log("fadein호출");
            var color = this.dim.color;
            color.a = 0;
            this.dim.color = color;
 
            float alpha = color.a;
            while (true)
            {
                alpha += 0.016f;
                color.a = alpha;
                this.dim.color = color;
                if (alpha >= 1)
                {
                    alpha = 1f;
                    break;
                }
                yield return null;
            }
            this.onFadeInComplete();
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
namespace minseok
{
    public class UILogo : UIBase
    {
        public override void Init(Camera uiCamera)
        {
            base.Init(uiCamera);
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class UITitle : UIBase
    {
        public override void Init(Camera uiCamera)
        {
            base.Init(uiCamera);
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class Character : MonoBehaviour
    {
        private Coroutine routine;
        public CharacterInfo info;
        public Animation anim;
        public GameObject model;
        public GameObject Model
        {
            get
            {
                return this.Model;
            }
            set
            {
                this.model = value;
                this.model.transform.SetParent(this.transform);
                this.anim = this.model.GetComponent<Animation>();
            }
        }
        
        public Character(CharacterInfo info, GameObject model)
        {
            this.info = info;
            this.Model = model;
        }
 
        public void Move(Character target, System.Action onCompleteMove)
        {
            StartCoroutine(this.MoveImpl(target, onCompleteMove));
            StopCoroutine(this.MoveImpl(target, onCompleteMove));
        }
        private IEnumerator MoveImpl(Character target, System.Action onCompleteMove)
        {
            Debug.Log("걸어간다");
            var data = DataManager.GetInstance();
            this.anim.Play(data.dicCharacterAnim[this.info.id].run_anim_name);
            var normVector = (target.transform.position - this.transform.position).normalized;
            var speed = normVector * 1.0f * Time.deltaTime;
            while(true)
            {
                var distance = Vector3.Distance(target.transform.position, this.transform.position);
                this.transform.position += speed;
                if(distance <= data.dicCharacterData[this.info.id].attack_range)
                {
                    break;
                }
                yield return null;
            }
            onCompleteMove();
        }
 
        public void Attack(Character target, System.Action onCompleteAttack)
        {
            if (this.routine != null)
            {
                StopCoroutine(this.routine);
            }
            this.routine = StartCoroutine(this.AttackImpl(target, onCompleteAttack));
        }
        private IEnumerator AttackImpl(Character target, System.Action onCompleteAttack)
        {
            Debug.Log("공격한다");
            var data = DataManager.GetInstance();
            this.anim.Play(data.dicCharacterAnim[this.info.id].attack_anim_name);
            yield return new WaitForSeconds(0.26f);
 
            Debug.LogFormat("{0}에게 {1}의 데미지를 입혔습니다!", data.dicCharacterData[target.info.id].name, data.dicCharacterData[this.info.id].damage);
            target.TakeDamage(data.dicCharacterData[this.info.id].damage);
            yield return new WaitForSeconds(0.86f);
 
            onCompleteAttack();
        }
 
        public void TakeDamage(int damage)
        {
            this.info.hp -= damage;
            if(this.info.hp <= 0)
            {
                this.anim.Play(DataManager.GetInstance().dicCharacterAnim[this.info.id].die_anim_name);
            }
        }
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class CharacterAnimData
    {
        public int id;
        public string attack_anim_name;
        public string damage_anim_name;
        public string idle_anim_name;
        public string run_anim_name;
        public string die_anim_name;
    }
 
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class CharacterData
    {
        public int id;
        public string prefab_name;
        public string name;
        public int hp;
        public int damage;
        public float attack_range;
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
namespace minseok
{
    public class CharacterInfo
    {
        public int id;
        public int hp;
        public Vector3 position;
 
        public CharacterInfo(int id, int hp, Vector3 position)
        {
            this.id = id;
            this.hp = hp;
            this.position = position;
        }
    }
}
 
cs


'Unity > 과제' 카테고리의 다른 글

Isometric, 클릭시 좌표 출력하기  (0) 2019.05.13
2D Running Game 기본 시스템 만들기  (0) 2019.05.09
왔다갔다 때리기  (0) 2019.04.16
0  (0) 2019.04.11
:

왔다갔다 때리기

Unity/과제 2019. 4. 16. 08:46
코루틴은 사용 후 항상 stop할 것

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public partial class App : MonoBehaviour
{
    private eSceneType sceneType;
 
    private void Awake()
    {
        this.sceneType = eSceneType.None;
        Object.DontDestroyOnLoad(this);
    }
 
    // Start is called before the first frame update
    void Start()
    {
        this.LoadScene(eSceneType.Logo);
    }
 
    private void LoadScene(eSceneType sceneType)
    {
        AsyncOperation asyncOperation = null;
        if(this.sceneType != sceneType)
        {
            this.sceneType = sceneType;
            asyncOperation = SceneManager.LoadSceneAsync((int)sceneType);
            asyncOperation.completed += (ao) =>
            {
                switch (this.sceneType)
                {
                    case eSceneType.Logo:
                        {
                            this.LoadScene(eSceneType.Title);
                        }
                        break;
                    case eSceneType.Title:
                        {
                            this.LoadScene(eSceneType.DataLoad);
                        }
                        break;
                    case eSceneType.DataLoad:
                        {
                            this.LoadScene(eSceneType.InGame);
                        }
                        break;
                    case eSceneType.InGame:
                        {
                            var inGame = GameObject.FindObjectOfType<InGame>();
                            inGame.Init();
                        }
                        break;
                }
            };
 
        }
    }
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public partial class App : MonoBehaviour
{
    public enum eSceneType
    {
        None = -1,
        App = 0,
        Logo = 1,
        Title = 2,
        DataLoad = 3,
        InGame = 4
    }
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Character : MonoBehaviour
{
    public CharacterInfo info;
    public Animation anim;
    private GameObject model;
    public GameObject Model
    {
        get
        {
            return this.model;
        }
        set
        {
            this.model = value;
            this.model.transform.SetParent(this.transform);
            this.anim = this.model.GetComponent<Animation>();
        }
    }
    public System.Action OnAttackComplete;
    private Coroutine routine;
 
    //생성자
    public Character(CharacterInfo info)
    {
        this.info = info;
    }
 
    //이동메서드
    public void Move(Vector3 targetPosition, System.Action onCompleteMove)
    {
        Debug.Log("Move호출");
        if(routine != null)
        {
            StopCoroutine(this.routine);
        }
        this.routine = StartCoroutine(this.MoveImpl(targetPosition, onCompleteMove));
    }
 
    //이동코루틴
    private IEnumerator MoveImpl(Vector3 targetPosition, System.Action onCompleteMove)
    {
 
        Debug.Log("moveImpl 호출");
        this.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.info.id].run_anim_name);
        var normVector = (targetPosition - this.transform.position).normalized;
        var speed = 1.0f;
        var moveVector = normVector * speed * Time.deltaTime;
        while(true)
        {
            this.transform.position += moveVector;
            var distance = Vector3.Distance(targetPosition, this.transform.position);
            if(distance <= 0.5f)
            {
                break;
            }
            yield return null;
        }
        onCompleteMove();
    }
 
    //공격메서드
    public void Attack(Character target)
    {
        Debug.Log("Attack 호출");
        if (routine != null)
        {
            StopCoroutine(this.routine);
        }
 
        this.routine = StartCoroutine(this.AttackImpl(target));
    }
 
    //공격코루틴
    private IEnumerator AttackImpl(Character target)
    {
        Debug.Log("attackImpl 호출");
        var attackAnimName = DataManager.GetInstance().dicCharacterAnimData[this.info.id].attack_anim_name;
        this.anim.Play(attackAnimName);
        yield return new WaitForSeconds(0.26f);
 
        Debug.LogFormat("{0}에게 {1}의 데미지를 입혔습니다!", DataManager.GetInstance().dicCharacterData[target.info.id].name, DataManager.GetInstance().dicCharacterData[this.info.id].damage);
        target.GetDamage(DataManager.GetInstance().dicCharacterData[this.info.id].damage);
        yield return new WaitForSeconds(0.46f);
        
        this.OnAttackComplete();
    }
 
    //피해메서드
    public void GetDamage(int damage)
    {
        this.info.hp -= damage;
        if (this.info.hp <= 0)
        {
            this.gameObject.GetComponentInChildren<Animation>().Play(DataManager.GetInstance().dicCharacterAnimData[this.info.id].die_anim_name);
        }
        else
        {
            this.gameObject.GetComponentInChildren<Animation>().Play(DataManager.GetInstance().dicCharacterAnimData[this.info.id].hit_anim_name);
        }
    }
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public class DataLoad : MonoBehaviour
{
    private AsyncOperation asyncOperation;
 
    // Start is called before the first frame update
    void Start()
    {
        //데이터 로드, 데이터 적재
        Debug.Log("DataLoad 씬 Start()");
        DataManager dataManager = DataManager.GetInstance();
        dataManager.LoadDatas();
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
 
public class DataManager
{
    private static DataManager instance;
    public Dictionary<int, CharacterData> dicCharacterData;
    public Dictionary<int, CharacterAnimData> dicCharacterAnimData;
 
    //생성자
    private DataManager()
    {
        this.dicCharacterAnimData = new Dictionary<int, CharacterAnimData>();
        this.dicCharacterData = new Dictionary<int, CharacterData>();
    }
 
    //인스턴스리턴
    public static DataManager GetInstance()
    {
        if(DataManager.instance == null)
        {
            DataManager.instance = new DataManager();
        }
        return DataManager.instance;
    }
 
    //제이슨 파일로드
    public void LoadDatas()
    {
        //캐릭터데이터
        var textAsset = Resources.Load<TextAsset>("Datas/character_data");
        var json = textAsset.text;
        var arrJson = JsonConvert.DeserializeObject<CharacterData[]>(json);
        foreach (var data in arrJson)
        {
            this.dicCharacterData.Add(data.id, data);
        }
        //애니메이션데이터
        var textAsset2 = Resources.Load<TextAsset>("Datas/character_anim_data");
        var json2 = textAsset2.text;
        var arrJson2 = JsonConvert.DeserializeObject<CharacterAnimData[]>(json2);
        foreach (var data in arrJson2)
        {
            this.dicCharacterAnimData.Add(data.id, data);
        }
        Debug.LogFormat("dicCharacterData  {0}개"this.dicCharacterData.Count);
        Debug.LogFormat("dicCharacterAnimData  {0}개"this.dicCharacterAnimData.Count);
    }
 
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class InGame : MonoBehaviour
{
    private Character hero;
    private Character monster;
    private bool completeMethod;
 
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("InGame Start 메서드 실행");
        this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.hero.info.id].idle_anim_name);
        this.monster.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.monster.info.id].idle_anim_name);
 
        this.hero.Move(this.monster.transform.position, () =>
        {
            Debug.Log("사정거리에 도달했습니다.");
            this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.hero.info.id].idle_anim_name);
            this.hero.Attack(this.monster);
        });
        this.hero.OnAttackComplete = () => {
 
            this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.hero.info.id].idle_anim_name);
            if (this.monster.info.hp > 0)
            {
                this.hero.Attack(this.monster);
            }
            else
            {
                this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.hero.info.id].idle_anim_name);
            }
        };
 
        this.hero.transform.LookAt(new Vector3(101));
        this.hero.Move(new Vector3(101), () =>
        {
            Debug.Log("초기위치에 도달했습니다.");
            this.hero.anim.Play(DataManager.GetInstance().dicCharacterAnimData[this.hero.info.id].idle_anim_name);
        });
    }
 
    public void Init()
    {
        Debug.Log("InGame 스크립트의 Init메서드 호출");
        var data = DataManager.GetInstance();
        this.hero = this.CreateCharacter(0);
 
        this.monster = this.CreateCharacter(1);
        this.hero.transform.position = new Vector3(101);
        this.monster.transform.position = new Vector3(505);
        this.hero.transform.LookAt(this.monster.transform);
        this.monster.transform.LookAt(this.hero.transform);
    }
 
    public Character CreateCharacter(int id)
    {
        var data = DataManager.GetInstance();
 
        //캐릭터생성
        var characterPrefab = Resources.Load<GameObject>("Prefabs/Character");
        var characterGo = GameObject.Instantiate<GameObject>(characterPrefab);
        var modelPrefab = Resources.Load<GameObject>(data.dicCharacterData[id].prefab_name);
        var modelGo = GameObject.Instantiate<GameObject>(modelPrefab);
        var character = characterGo.AddComponent<Character>();
        character.Model = modelGo;
        character.name = data.dicCharacterData[id].name;
        character.info = new CharacterInfo(id, data.dicCharacterData[id].anim_data_id, data.dicCharacterData[id].hp);
        character.transform.position = character.info.position;
 
        Debug.Log("캐릭터 생성됨");
        return character;
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public class Logo : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Logo씬 스크립트의 Start메서드가 호출됨");
        Debug.Log("Logo를 보여줍니다.");
    }
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public class Title : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Title Scene Title Script 호출");
        Debug.LogFormat("DataLoad씬 호출완료");
    }
}
 
cs


'Unity > 과제' 카테고리의 다른 글

Isometric, 클릭시 좌표 출력하기  (0) 2019.05.13
2D Running Game 기본 시스템 만들기  (0) 2019.05.09
씬 전환 및 가서 공격하기  (0) 2019.04.16
0  (0) 2019.04.11
: