게임클라이언트 프로그래밍/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가 들어온다면 공격 가능 / 아니면 공격 불가