[Unity] 2019-11-11 Study002 캐릭터의 이동, 애니메이션, grandchild 찾기

APP 2019. 11. 12. 08:46

App에서

Charactetr0201, Character0301, Sword 게임오브젝트 생성.

 

Character0201의 grandchild 중 하나인 dummyRHand 게임오브젝트를 찾아서 Sword를 자식으로 설정.

 

Character0301의 dymmyRHand 게임오브젝트를 찾아서 Character0201이 가지고 있는 Sword를 옮김.

 

 

 

App.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;


public class App : MonoBehaviour
{
    //private Dictionary<int, CharacterData> dicCharacterData;
    //private Hero hero;
    //private Monster monster;
    GameObject character0201Prefab;
    GameObject character0301Prefab;
    GameObject swordPrefab;

    // Start is called before the first frame update
    private void Awake()
    {
        //this.dicCharacterData = new Dictionary<int, CharacterData>();
        character0201Prefab = Resources.Load<GameObject>("Prefabs/ch_02_01");
        character0301Prefab = Resources.Load<GameObject>("Prefabs/ch_03_01");
        swordPrefab = Resources.Load<GameObject>("Prefabs/ch_sword_01");

    }

    private void Start()
    {
        //Character0201 생성
        GameObject character0201Go = new GameObject("Character0201");
        GameObject character0201Model = Instantiate(character0201Prefab);
        character0201Model.transform.SetParent(character0201Go.transform, false);


        //Sword 생성
        GameObject swordGo = new GameObject("Sword");
        GameObject swordModel = Instantiate(swordPrefab);
        swordModel.transform.SetParent(swordGo.transform, false);
        swordModel.transform.position = Vector3.zero;

        GameObject aGo = Resources.Load<GameObject>("Prefabs/A");
        var dummy = GameUtils.SearchHierarchyForBone(aGo.transform, "F");
        //Character0201의  dummyRHand찾기
        var dummyRHandOfCh0201 = TransformDeepChildExtension.FindDeepChild(character0201Go.transform, "DummyRHand");
        //Debug.Log(dummyRHandOfCh0201);

        //var dummy3 =GameUtils.SearchHierarchyForBone(character0201Go.transform, "DummyRHand");
        //Debug.Log(dummy3);

        //Sword의 부모로 Character0201의  dummyRHand 지정
        swordGo.transform.SetParent(dummyRHandOfCh0201.transform, false);

        //Character0301 생성
        GameObject character0301Go = new GameObject("Character0301");
        character0301Go.transform.position = new Vector3(2, 0, 0);
        GameObject character0301Model = Instantiate(character0301Prefab);
        character0301Model.transform.SetParent(character0301Go.transform, false);

        //Character0301의  dummyRHand찾기
        var dummyRHandOfCh0301 = TransformDeepChildExtension.FindDeepChild(character0301Go.transform, "DummyRHand");
        //Debug.Log(dummyRHandOfCh0301);

        //Sword의 부모로 Character0301의  dummyRHand 지정
        swordGo.transform.SetParent(dummyRHandOfCh0301.transform, false);

        //var cube = character0201Go.transform.FirstChildOrDefault(x => x.name == "ch_02_01(Clone)");

        //Debug.Log(cube);


    }
    //재귀적으로 자식을 찾는 방법인데 동작에 오류가 있음
    GameObject RecursiveFindChild(Transform parent, string childName)
    {
        foreach (Transform child in parent)
        {
            if (child.name == childName)
                return child.gameObject;
            else
                return RecursiveFindChild(child, childName);
        }

        return null;
    }

    //public GameObject FindGrandChild(string name,GameObject go)
    //{
    //    var findResult = go.transform.Find(name);
    //    if (findResult)
    //    {
    //        for(int i =0; i <go.transform.childCount; i)


    //    }


    //}





    /* 몬스터 & 히어로 Box모양 캐릭터 두개 생성 후 지정된 좌표로 움직이고 서로를 바라봄
    //void Start()
    //{
        //string path = "Data/character_data";
        //var json = Resources.Load<TextAsset>(path).text;

        //Debug.Log(json);

        //var arrCharacterDatas = JsonConvert.DeserializeObject<CharacterData[]>(json);

        //foreach (CharacterData data in arrCharacterDatas)
        //{
        //    dicCharacterData.Add(data.id, data);
        //}
        //var hero = CreateCharcter(200);
        //hero.Init(Vector3.zero);
        //this.hero = hero;
        //var monster = CreateCharcter(100);
        //monster.Init(new Vector3(2, 0, 0));
        //this.monster = monster;


        //var dist = Vector3.Distance(monster.transform.position, hero.transform.position);
        //var normal = (monster.transform.position - hero.transform.position).normalized;


        //Debug.Log(normal.magnitude);

    //}
    //public T CreateCharcter(int id) where T : Character
    //{
        //var data = this.dicCharacterData[id];
        ////캐릭터 객체의 생성
        ////Shell GameObject(해당 스크립트가)
        //GameObject characterGo = new GameObject(data.name);
        //var character = characterGo.AddComponent();
        ////Model
        //var path = string.Format("Prefabs/{0}", data.prefab_name);

        //var prefab = Resources.Load<GameObject>(path);
        //var model = Instantiate(prefab);

        ////Data(정확히는 Info)
        //CharacterInfo info = new CharacterInfo()
        //{
        //    id = data.id,
        //    hp = data.hp
        //};


        //character.SetModel(model);
        //character.SetInfo(info);
        //return character;

    //}


    // Update is called once per frame
    void Update()
    {
        //var speed = 1f;
        //var heroEndPositon = new Vector3(3, 0, 5);
        //hero.transform.position = Vector3.MoveTowards(hero.transform.position, heroEndPositon, speed*1.5f* Time.deltaTime);
        //hero.transform.forward = heroEndPositon;
        ////hero의 위치가 최종위치가 아니면 달리는 모션으로 설정
        //hero.transform.GetComponentInChildren().SetBool("Run Forward", hero.transform.position != heroEndPositon);
        //if (hero.transform.position == heroEndPositon)
        //{
        //    hero.transform.LookAt(monster.transform);
        //}

        //var monsterEndPosition = new Vector3(2, 0, 7);
        //monster.transform.position = Vector3.MoveTowards(monster.transform.position, monsterEndPosition, speed*1* Time.deltaTime);
        //monster.transform.forward = monsterEndPosition;
        //monster.transform.GetComponentInChildren().SetBool("Walk Forward", monster.transform.position != monsterEndPosition);
        //if(monster.transform.position == monsterEndPosition)
        //{
        //    monster.transform.LookAt(hero.transform);
        //}

    }
    */
}

Character.cs

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

public class Character : MonoBehaviour
{
    private GameObject model;
    private CharacterInfo info;
    // Start is called before the first frame update
    void Start()
    {
        
    }
    public void Init(Vector3 pos)
    {
        this.transform.position = pos;
    }
    public void SetModel(GameObject model)
    {
        this.model = model;
        this.model.name = "model";
        var oldModel = this.transform.Find("model");
        if (oldModel != null)
        {
            Destroy(oldModel.gameObject);
        }
        this.model.transform.SetParent(this.transform, false);
        this.model.transform.localPosition = Vector3.zero;
    }

    public void SetInfo(CharacterInfo info)
    {
        this.info = info;
    }
    // Update is called once per frame
    void Update()
    {

    }  
}

CharcterData.cs

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

public class CharacterData
{
    public int id;
    public string name;
    public int hp;
    public int damage;
    public float attack_range;
    public string prefab_name;
}

CharacterInfo.cs

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

public class CharacterInfo
{
    public int id;
    public int hp;    
}

Hero.cs

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

public class Hero : Character
{
   
    // Start is called before the first frame update
    void Start()
    {
        
    }
   
    
}

Monster.cs

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

public class Monster : Character
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

 

 

grandchild를 찾는 API No.1

 

GameUtils.cs

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

public static class GameUtils
{
    //HOW TO USE
    //var cube = this.transform.FirstChildOrDefault(x => x.name == "deeply_nested_cube");
    public static Transform FirstChildOrDefault(this Transform parent, Func<Transform, bool> query)
    {
        if (parent.childCount == 0)
        {
            return null;
        }

        Transform result = null;
        for (int i = 0; i < parent.childCount; i++)
        {
            var child = parent.GetChild(i);
            if (query(child))
            {
                return child;
            }
            result = FirstChildOrDefault(child, query);
        }

        return result;
    }


    public static Transform SearchHierarchyForBone(Transform current, string name)
    {
        //sb.Append(current.name + "\n");

        // check if the current bone is the bone we're looking for, if so return it
        if (current.name == name)
            return current;

        // search through child bones for the bone we're looking for
        for (int i = 0; i < current.childCount; ++i)
        {
            // the recursive step; repeat the search one step deeper in the hierarchy
            var child = current.GetChild(i);

            Transform found = SearchHierarchyForBone(child, name);

            // a transform was returned by the search above that is not null,
            // it must be the bone we're looking for
            if (found != null)
                return found;
        }

        // bone with name was not found
        return null;
    }
}

 

grandchild를 찾는 API No.2

 

TraTransformDeepChildExtension.cs

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

public static class TransformDeepChildExtension
{
    //Breadth-first search
    public static Transform FindDeepChild(this Transform aParent, string aName)
    {
        Queue<Transform> queue = new Queue<Transform>();
        queue.Enqueue(aParent);
        while (queue.Count > 0)
        {
            var c = queue.Dequeue();
            if (c.name == aName)
                return c;
            foreach (Transform t in c)
                queue.Enqueue(t);
        }
        return null;
    }
}

 

 

 

 

 

 

/*로 주석처리된 몬스터 & 히어로 부분 실행결과

App의 멤버변수 dicCharacterData, hero, monster 도 주석처리 해제 하고,

Awake 메서드의 this.dicCharacterData = new Dictionary<int, CharacterData>(); 도 주석처리 해제해야함

 

 

: