HeroShoot-Stage1 오류 수정: 자식 오브젝트 받기(GetComponentInChildren/GetChild)
2023. 8. 28.

-이전 포스팅에서 GetChild로 작성했을때 비활성화되어있던 target을 받아오려니 오류가 발생했는데 87~88라인과 같이 수정하여 해결하였다.

GetComponentInChildren<T>(bool includInactive)는 컴포넌트를 T로 받아 자식을 찾는다. 

-includeInactive 인자를 생략하면 false값이 반영된다. 처음에는 인자를 생략해서 이 경우에도 자식을 제대로 찾지 못했다.

 

=> 즉, 비활성화된 게임오브젝트의 컴포넌트는 반환하지 않는다. 위의 경우에서는 비활성화된 target을 찾아야하므로 true로 작성했다.

 

https://docs.unity3d.com/ScriptReference/Component.GetComponentsInChildren.html

 

Unity - Scripting API: Component.GetComponentsInChildren

The typical usage for this method is to call it from a MonoBehaviour script (which itself is a type of component), to find references to other Components or MonoBehaviours attached to the same GameObject as that script, or its child GameObjects. In this ca

docs.unity3d.com

비활성화 해둔 target
수정 후 구현결과

-Player가 움직이고 있더라도 indicator가 나타나도록 수정

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.EventSystems;

public class PlayerController : MonoBehaviour
{
    //[SerializeField] private VariableJoystick joystick;
    public enum eState
    {// 상태 정의
        IDLE, MOVE, ATTACK, DIE
    }
    public eState state = eState.IDLE;//Player의 현재 상태
    private bool isDie;//Player의 사망 여부
    
   // [SerializeField] private float traceDistance = 10.0f;//추적 사거리
    [SerializeField] private float attackDistance = 8.0f;//공격 사거리
    [SerializeField] private float moveSpeed = 3f;
    [SerializeField] GameObject bulletGo;//총알 오브젝트
    [SerializeField] Transform FirePos;//총알 발사 transform
    private float distance;
    private float minDistance = 20f;
    private GameObject shortDistanceGo;
    private float monsterCount;
    private TutorialMain tutorialMain;
    private Stage1Main stage1; 
    private Transform monsterTrans;
    private SceneLoad sceneLoad;
    private Collision collision;
    public bool isMove = false;
    private GameObject go;
    private List<MonsterController> monsterList = new List<MonsterController>();
  //  private Vector3 downPosition;
    //private bool isDown = false;
    public Animator anim;
    
    // Start is called before the first frame update
    void Start()
    {
      this.tutorialMain = FindObjectOfType<TutorialMain>();
      this.stage1 = FindObjectOfType<Stage1Main>(); 
      //this.monsterGenerator = FindObjectOfType<MonsterGenerator>();
      this.sceneLoad = FindObjectOfType<SceneLoad>();
      this.monsterList = this.stage1.monsterList;//stage1의 몬스터를 저장
      //  StartCoroutine(this.CoMonsterLoad());
        StartCoroutine(this.CheckState());//상태확인
        StartCoroutine(this.PlayerAction());//상태에따라 플레이어 동작
    }

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


    }
    private IEnumerator CoMonsterLoad()
    {
        yield return null;
        //this.monsterTrans = this.stage1.monsterList[0].gameObject.transform;
        this.monsterTrans = this.monsterList[0].gameObject.transform;
        Debug.Log(this.monsterTrans);

    }
    private IEnumerator CheckState()
    {//상태 갱신 코루틴 함수: 일정 간격으로 Player의 행동상태 체크
        while (!isDie)
        {
            Debug.Log(distance);
            //yield return null;
            yield return new WaitForSeconds(0.3f);//0.3초마다 상태 갱신
            //yield return new WaitForSeconds(0.3f);
            this.DetectMonster();//가장 가까운 몬스터 감지
            if (this.isMove)
            {//움직이는 동안        
                this.state = eState.MOVE;
                if (this.distance != 0 && this.distance < this.attackDistance)
                {
                    this.showTarget();
                }
                else
                {
                    this.go?.SetActive(false);
                }
            }
            else
            {//움직이지 않을 때
                if (shortDistanceGo != null)
                {//몬스터 존재시
                    if (this.distance < this.attackDistance)
                    {
                        this.showTarget();
                        this.transform.LookAt(this.shortDistanceGo.transform.position);
                        this.state = eState.ATTACK;//공격상태로 변경                      
                        this.Fire();//총알 발사
                     //   Debug.Log(this.distance);                       
                    }
                    else //공격범위를 벗어나면
                    {                     
                       this.go?.SetActive(false);
                        yield return null;
                        this.state = eState.IDLE;              
                    }
                }
                else//몬스터가 존재하지 않으면
                {
                    this.state = eState.IDLE;                
                }           
            }
        }
        
    }
    private void showTarget()
    {
        this.go = this.shortDistanceGo.GetComponentInChildren<MeshRenderer>(true).gameObject;
        this.go.SetActive(true);
    }
    private IEnumerator PlayerAction()
    {
        while (!isDie)
        {
            yield return new WaitForSeconds(0.3f);
            if (this.state == eState.MOVE)
            {
                Debug.Log("Move");
                this.anim.SetInteger("State", 1);
            }
            else if(this.state == eState.ATTACK)
            {
                Debug.Log("Attack Monster!");
                this.anim.SetInteger("State", 2);
            }         
            else
            {
                this.anim.SetInteger("State", 0);
            }
        }
    }
    public void movePlayer(Vector3 dir)
    {
        float angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;

        this.transform.Translate(dir.normalized * this.moveSpeed * Time.deltaTime, Space.World);
        this.transform.localRotation = Quaternion.AngleAxis(angle, Vector3.up);//축으로 회전
                                                                               
        //this.anim.SetInteger("State", 1);//run forward animation
      
    }
    private void Fire()
    {
       // Vector3 rotation = this.FirePos.rotation.eulerAngles;
     //   Quaternion rotation = this.FirePos.rotation +Quaternion(0,0,0)
        Instantiate(this.bulletGo,this.FirePos.position,this.FirePos.rotation);
        
        //go.transform.rotation = Quaternion.identity;
        // go.transform.position = this.FirePos.position;
    }
    private void DetectMonster()
    {//주변에 있는 몬스터 추출
        Collider[] colls = Physics.OverlapSphere(this.transform.position, this.attackDistance, 1 << 3);
        
        foreach (Collider coll in colls)
        { 
           // Debug.Log(coll);            
            this.distance = Vector3.Distance(this.transform.position, coll.gameObject.transform.position);
         
                if (this.minDistance >= this.distance)//거리 측정
                {//distance가 더 작을때 shorDistanceGo에 게임 오브젝트를 저장
                    this.minDistance = this.distance;
                    this.shortDistanceGo = coll.gameObject;
                    Debug.LogFormat("가장 가까운 몬스터:{0}", coll.gameObject.name);
                    
                 }           
        }

    }
    private void OnCollisionEnter(Collision collision)
    {
        this.collision = collision;//매개변수를 멤버변수에 저장
        if (collision.collider.CompareTag("Portal"))
        {
            Debug.Log("Portal");
            Destroy(collision.gameObject);
            this.tutorialMain.OpenGate();
        }
        else if (collision.collider.CompareTag("Obstacle"))
        {

        }
        else if (collision.collider.CompareTag("Stage1"))
        {
            this.SceneLoad(this.collision.gameObject.tag);
        }
        else if (collision.collider.CompareTag("Stage2"))
        {
            this.SceneLoad(this.collision.gameObject.tag);
        }
    }

    private void SceneLoad(string sceneName)
    {
        this.sceneLoad.imgDim.gameObject.SetActive(true);
        StartCoroutine(this.sceneLoad.CoFadeOut(sceneName));
    }

    private void OnDrawGizmos()
    {
        if(this.state == eState.ATTACK)
        {
            Gizmos.color = Color.yellow;
            
        }
    }
}

 

 

myoskin