게임클라이언트 프로그래밍/Unity

3D 캐릭터 이동,시야, 공격 애니매이션 구현

Game Client Lee Hwanguk 2023. 3. 3. 02:05

#캐릭터의 이동,애니매이션 구현

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

public class Hero : MonoBehaviour
{
    private GameObject modelGo;
    public enum eState
    {
        None=-1, Idle, Run, Attack
    }
    public float radius = 30;
    public Transform target;
    private Animator anim;
    private Vector3 dir;
    private eState state;
    private Coroutine routine;
    public float speed = 1f;

    public void Init(GameObject modelGo)
    {
        this.modelGo = modelGo;
        this.modelGo.name = "model";
        this.modelGo.transform.SetParent(this.transform);
    }
    private void Start()
    {
        this.anim = this.modelGo.GetComponent<Animator>();

    }
    private void Update()
    {

        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (this.routine != null) StopCoroutine(this.routine); //코루틴이 돌고있다면? 코루틴 중지
            this.routine = this.StartCoroutine(this.CorAttack()); 
        }

        if (this.state != eState.Attack)
        {
            var h = Input.GetAxisRaw("Horizontal");
            var v = Input.GetAxisRaw("Vertical");
            dir = Vector3.Normalize(new Vector3(h, 0, v));

            if (dir != Vector3.zero) //di r가 Vector3(0,0,0)이 아니라면
            {
                var angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
                this.modelGo.transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);
                
                //Player의 이동
                this.anim.SetInteger("State", 1); //Run
                this.transform.Translate(this.modelGo.transform.forward * this.speed * Time.deltaTime, Space.World); //이동
                this.state = eState.Run;
            }
            else //dir Vector가 (0,0,0)이면 정지(Idle)
            {
                this.state = eState.Idle;
                this.anim.SetInteger("State", 0); 
            }
        }
    }
    private IEnumerator CorAttack()
    {
        this.anim.SetInteger("State", 2); 
        var prevState = this.state; 

        this.state = eState.Attack;
        Debug.LogFormat("state: <color=red>{0}</color>", this.state);

        yield return new WaitForSeconds(0.5f);

        if (prevState == eState.Run) 
        {
            this.anim.SetInteger("State", 1);
            this.state = eState.Run;
        }
        else if (prevState == eState.Idle)
        {
            this.anim.SetInteger("State", 0);
            this.state = eState.Idle;
        }
    }
    private void OnDrawGizmos()
    {
        //DrawExtension.DrawGizmosCircle(this.transform.position, this.transform.up, 1, 20);    
        //DrawArrow.ForGizmo(this.transform.position, this.transform.forward, Color.blue);
        //DrawExtension.DrawWireArc(this.transform.position, this.transform.forward, this.radius, 1);
    }
}

#Attack과 Run을 이어주는걸 깜빡한다  둘을 이어주지않으면 Attack에서 애니매이션이 멈춰버리는 오류가 발생한다

 

#캐릭터의 시야 만들어주기

 

#Monster생성 (Hero의 생성방식과 동일하게 ->GameMain에서 MonsterShell 생성, Monster스크립트에서 monsterPrefab생성)

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

public class GameMain : MonoBehaviour
{
    public GameObject heroShellPrefab;    //hero prefab
    public GameObject MonsterShell;      //monster prefab
    public void Init(int selectedCharacterId) {
        Debug.LogFormat("[GameMain] selectedCharacterId: {0}", selectedCharacterId);
        this.CreateHero(selectedCharacterId);
        this.CreatMonster();
    }
    private void Start()
    {
        
    }

    private void CreateHero(int id) //hero 
    {
        //껍데기 만들기 
        var shellGo = Instantiate(this.heroShellPrefab);
        var hero = shellGo.GetComponent<Hero>();

        //모델 
        var data = DataManager.instance.GetCharacterData(id);
        var prefab = AssetManager.instance.GetPrefab(data.prefab_name);
        var modelGo = Instantiate(prefab);
        hero.Init(modelGo);
    }
    private void CreatMonster() //monster
    {
        var shellGo = Instantiate(this.MonsterShell);
        var monsterGo=shellGo.GetComponent<Monster>();
        monsterGo.Init();
    }


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

public class Monster : MonoBehaviour
{
    public GameObject monsterModerGo;


    public void Init()
    {       
        var monsterGo=Instantiate(this.monsterModerGo);
        monsterGo.name = "model";
        monsterGo.transform.SetParent(this.transform);
    }
    void Start()
    {
        
    }

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

#캐릭터의 시야에 Monster가 들어온다면 공격 가능 / 아니면 공격 불가