Unity/수업내용
2020-05-11 유니티 수업내용
J월드
2020. 5. 11. 10:21
유니티 생명주기 복습
더보기
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
|
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class App : MonoBehaviour
{
//인스턴스가 호출될때 한번.
//단, 게임오브젝트가 비활성화일 경우 호출 안됨.
//하지만, 게임오브젝트가 활성화이고, 컴포넌트가 비활성화일시에는 호출됨
private void Awake()
{
Debug.Log("App::Awake");
//태그로 씬에서 객체 찾기
//var mainCamera = GameObject.FindWithTag("MainCamera");
//Debug.LogFormat("mainCamera : {0}", mainCamera);
//var dummyRHand = GameObject.FindWithTag("DummyRHand");
//Debug.LogFormat("dummyRHand : {0}", dummyRHand);
//Go를 비활성화 하면 못찾음 ----> 잘 기억해두기 나중에 고통받음
//var player = GameObject.FindWithTag("Player");
//Debug.LogFormat("player : {0}", player);
}
//게임 오브젝트가 활성화 되었을 경우 호출됨.
//단, 게임오브젝트가 비활성화일 경우 호출 안됨.
//게임오브젝트가 활성화이고 컴포넌트가 비활성화일 경우도 호출 안됨
private void OnEnable()
{
Debug.Log("App::OnEnable");
}
//오브젝트가 활성화 상태일 경우 업데이트 함수 호출전에 한번만 호출됨
//단, 게임오브젝트가 비활성화일 경우 호출 안됨.
void Start()
{
Debug.Log("App::Start");
}
// 오브젝트가 활성화 상태일 경우 매프레임마다 호출됨.
//단, 게임오브젝트가 비활성화일 경우 호출 안됨.
void Update()
{
Debug.Log("App::Update");
}
//오브젝트가 비활성화일 경우 호출됨
//인스턴스화 될때 게임오브젝트가 비활성화, 컴포넌트가 비활성일경우 호출안됨
//인스턴스화 되고 오브젝트또는 컴포넌트가 활성화에서 비활성화 되었을경우 호출됨
private void OnDisable()
{
Debug.Log("App::OnDisable");
}
//Object.Destroy
//씬 종료
//오브젝트 존재의 마지막 프레임에 대해 모든 프레임 업데이트를 마친 후 이 함수가 호출됩니다.
//오브젝트 활성화, 컴포넌트 활성화 :
//Awake - OnEnable - Start - Update - OnDisable - OnDestroy
//오브젝트 활성화, 컴포넌트 비활성화 :
//Awake - OnDestroy
//오트젝트 비활성화, 컴포넌트 활성화 : X
private void OnDestroy()
{
Debug.Log("App::OnDestroy");
}
}
|
3초뒤에 씬바꾸기
더보기
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;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
public class App : MonoBehaviour
{
private float nextSceneCounter;
private bool isTitleScene;
private void Awake()
{
//앱은 어플리케이션의 매니져이기 때문에 씬이 바뀌더라도 항상 메모리에 로드되어있어야함
//하지만 SceneManager.LoadScene("Logo"); 만 했을때는 App은 사라지고, Logo씬만 남음.
//그걸 방지 하기 위해 아래 키워드를 사용함.
UnityEngine.Object.DontDestroyOnLoad(this.gameObject);
}
private void Start()
{
//Logo씬으로 전환
SceneManager.LoadScene("Logo");
}
private void LoadTitle(float time)
{
//조건식설정.. 잘하기, 한번 켜지면 다시 로드안되게 하는법
//생각좀하자....bool잘 이용
if (time >= 3 && !this.isTitleScene)
{
SceneManager.LoadScene("Title");
this.isTitleScene = true;
}
}
private void Update()
{
this.nextSceneCounter += Time.deltaTime;
this.LoadTitle(this.nextSceneCounter);
}
}
|
DataManager로 json파일을 불러와서 캐릭터 생성
App.class
더보기
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;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Linq;
public class App : MonoBehaviour
{
private float nextSceneCounter;
private bool isTitleScene;
private void Awake()
{
//앱은 어플리케이션의 매니져이기 때문에 씬이 바뀌더라도 항상 메모리에 로드되어있어야함
//하지만 SceneManager.LoadScene("Logo"); 만 했을때는 App은 사라지고, Logo씬만 남음.
//그걸 방지 하기 위해 아래 키워드를 사용함.
UnityEngine.Object.DontDestroyOnLoad(this.gameObject);
}
private void Start()
{
//Logo씬으로 전환
SceneManager.LoadScene("Logo");
DataManager.GetInstance().LoadDatas();
}
private void LoadTitle(float time)
{
//조건식설정.. 잘하기, 한번 켜지면 다시 로드안되게 하는법
//생각좀하자....bool잘 이용
if (time >= 3 && !this.isTitleScene)
{
SceneManager.LoadScene("Title");
this.isTitleScene = true;
}
}
private void Update()
{
this.nextSceneCounter += Time.deltaTime;
this.LoadTitle(this.nextSceneCounter);
}
}
|
DataManager.class
더보기
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
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.Linq;
public class DataManager
{
private static DataManager instance;
Dictionary<int, CharacterData> dicCharacterData;
private DataManager()
{
this.dicCharacterData = new Dictionary<int, CharacterData>();
}
public static DataManager GetInstance()
{
if (DataManager.instance == null)
{
DataManager.instance = new DataManager();
}
return DataManager.instance;
}
public void LoadDatas() {
//유니티에서 텍스트 파일은 TextAsset에 들어가있음
TextAsset textAsset = Resources.Load("Data/character_data") as TextAsset;
//.text가 문자열
string json = textAsset.text;
Debug.Log(json);
//역직렬화
var arrCharacterData = JsonConvert.DeserializeObject<CharacterData[]>(json);
//키로 검색을 빠르게 하기 위해서 사전에 등록
this.dicCharacterData = arrCharacterData.ToDictionary(x => x.id, x => x);
}
public CharacterData GetCharacterDataById(int id) {
return this.dicCharacterData[id];
}
}
|
CharacterData.class
더보기
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;
// MonoBehaviour 상속받지 않게 만듬
// 생명주기를 유니티가 관리하지 않음
// MonoBehaviour 상속받으면
// 컴포넌트됨, 인스턴스화 new 안됨
//MonoBehaviour 상속받지않으면
//컴포넌트 안됨, 인스턴스화 new 가능
public class CharacterData
{
public int id;
public string name;
public string res_name;
}
|
Title.class
더보기
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;
using UnityEngine.SceneManagement;
public class Title : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0)) //마우스 클릭시 Down 이벤트발생
{
Debug.Log("Down");
SceneManager.LoadScene("Lobby");
}
if (Input.GetMouseButtonUp(0)) //마우스 클릭후 뗄때 Up 이벤트발생
{
Debug.Log("Up");
}
}
}
|
Lobby.class
더보기
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.UI;
using UnityEngine.SceneManagement;
public class Lobby : MonoBehaviour
{
public Button btn;
public int characterId; //캐릭터 아이디 ingame으로 넘겨주기 위해 구멍하나 뚫음(나중에 버튼으로 구현)
// Start is called before the first frame update
void Start()
{
//DataManager.GetInstance().LoadDatas(); //Ingame 테스트하려고 데이터 로드
btn.onClick.AddListener(() =>
{
//Lobby 씬이 종료되기 전에 Ingame씬이 초기화(로드)될 시에 SceneManager_sceneLoaded 함수를 콜
//SceneManager.sceneLoaded += SceneManager_sceneLoaded; //메모리에 미리 올려둠(철수 진동벨 예시)
//SceneManager.LoadScene("InGame");
});
}
//SceneManager_sceneLoaded 함수 콜 할시 Ingame의 메인 스크립트에 접근해 값을 넘겨줌 그후에 Lobby씬은 종료
private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
{
//타입으로 가져오는 방법
//var inGame = GameObject.FindObjectOfType<InGame>();
//inGame.Init(this.characterId);
//Debug.LogFormat("inGame : {0}", inGame);
//해당이름으로 게임오브젝트를 가져옴(위와 같은 코드)
var inGameGo = GameObject.Find("Ingame");
var inGame = inGameGo.GetComponent<InGame>();
inGame.Init(this.characterId);
Debug.LogFormat("inGame : {0}", inGame);
}
// Update is called once per frame
void Update()
{
}
}
|
cs |
Ingame.class
더보기
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
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InGame : MonoBehaviour
{
private void Awake()
{
Debug.Log("InGame::Awake");
}
public void Init(int characterId) //초기화 함수 선언
{
Debug.LogFormat("Init : {0}", characterId);
var data = DataManager.GetInstance().GetCharacterDataById(characterId);
//data.res_name -> ch_01_01
var path = string.Format("Prefabs/{0}", data.res_name);
var prefab = Resources.Load<GameObject>(path);
var go = Instantiate(prefab);
go.transform.position = Vector3.zero; //0,0,0에 맞춤
}
// Start is called before the first frame update
void Start()
{
Debug.Log("인게임입니다..");
this.Init(100);
}
// Update is called once per frame
void Update()
{
}
}
|
cs |
대리자, 델리게이트 , 람다식
대리자(델리게이트)
액션 변수 += 메서드와 연결
메서드 호출
람다식 = 코드분리를 방지하기 위해 사용
Ingame.class
더보기
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
|
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.UI;
public class InGame : MonoBehaviour
{
public Hero hero;
public Button btn;
private void Start()
{
this.btn.onClick.AddListener(() => {
this.hero.onDieComplete += this.HeroDieComplete;
this.hero.Die();
});
this.hero.onMoveComplete += this.HeroMoveComplete;
this.hero.Move();
}
private void HeroMoveComplete()
{
Debug.Log("MoveComplete");
}
private void HeroDieComplete()
{
Debug.Log("DieComplete");
}
}
|
cs |
Hero.class
더보기
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
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class Hero : MonoBehaviour
{
public GameObject Model;
private Animation anim;
private Vector3 targetPostion;
private bool ismove;
private bool isDead;
public UnityAction onMoveComplete; //대리자 델리게이트
public UnityAction onDieComplete; //대리자 델리게이트
// Start is called before the first frame update
void Start()
{
this.targetPostion = new Vector3(0, 0, 2);
this.anim = this.Model.gameObject.GetComponent<Animation>();
}
public void Move()
{
this.ismove = true;
this.anim.Play("run@loop");
}
public void Stop()
{
this.ismove = false;
this.anim.Play("idle@loop");
}
public void Die()
{
this.isDead = true;
if (isDead == true)
{
this.Model.transform.position = this.transform.position;
}
this.anim.Play("die");
this.ismove = false;
}
// Update is called once per frame
void Update()
{
if (this.ismove)
{
var speed = 1;
var dir = Vector3.forward;
this.transform.Translate(speed * dir * Time.deltaTime);
var dis = Vector3.Distance(this.targetPostion, this.transform.position);
if (this.isDead)
{
this.onDieComplete(); //완료시에 델리게이트 콜
}
if (!this.isDead && dis <= 0.02f) // 완료
{
this.onMoveComplete(); //완료시에 델리게이트 콜
this.Stop();
}
}
}
}
|
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
|
GameObject.FindWithTag
보편적인 게임 구조
App - 로고 - 타이틀 - 로딩화면 - 로비 - 인게임
씬전환
씬 - 화면전체가 바뀜(꼭 그렇지 만도 않다)
-----------아래는 씬으로 보지않음---------
팝업 - 화면에 띄워지고 닫기버튼이 존재함
페이지 - 뒤로가기가 있으면 페이지
------------------------------------------------
메인카메라에서 skybox말고 solid color하면 배경화면 색을 단색으로 할수있음
- 카메라상에서만 흰색으로 보이는것이고 사실상 배경화면이 흰색이 아님
배경화면을 하려면, 이미지오브젝트를 하나더만들어서 순서바꿔줌
------------------------------------------------
이미지넣기(로고)
포토샵에서
이미지 받아와서 알파채널 이미지면, save for web(File - Export에있음).
유니티에서
Hierachy에서 오른쪽마우스 클릭 UI 탭에 Image
Assets에 Textures 파일만들어서 Logo 이미지파일넣고
이미지 눌러서 Inspector에 Texture Type을 Sprite(2D and UI)로 변경하고
캔버스 이미지 Inspector에 Image 컴포넌트 Source Image에 드래그 삽입
SetNativeSize 클릭
-------------------------------------------------
파일 - 빌드 세팅 - Scenes in Build 에 순서대로 끌어옴
씬전환
SceneManager.LoadScene("Lobby");
버튼 클릭처리 하기
씬전환 프로세스
App - Logo - Title - Lobby.
씬이 전환되면 모든 오브젝트가 다 메모리에서 내려감
--------------------------------------------------
Json 로드하기
유니티 스토어에서 Json 컨버터 다운로드
유니티에서 텍스트 파일은 TextAsset에 들어가있음
TextAsset textAsset = Resources.Load("Data/character_data") as TextAsset;
.text가 문자열
string json = textAsset.text;
|
cs |