
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;
public class BossController : MonoBehaviour
{
public Material[] mat = new Material[2];
public enum eState
{
IDLE = 0,
TRACE,
ClOSE_ATTACK, //근거리 공격
LONG_ATTACK, //원거리 공격
DIE,
}
public eState state;
[SerializeField]
private float closeAttackRange = 4.0f;
[SerializeField]
private float traceRange = 30.0f;
[SerializeField]
private float longAttackRange = 10.0f;
private readonly int hashState = Animator.StringToHash("State");
private float monsterHp = 160.0f;
public bool isDie;
private Animator anim;
private Transform playerTrans;
private Transform bossTrans;
private NavMeshAgent agent;
public float time = 0;
private bool isThrow = false;
[SerializeField]
private Transform firePos;
[SerializeField]
private GameObject SphereBomb;
private GameObject bodyMesh;
private GameObject shieldMesh;
private GameObject axeMesh;
private float currHp;
private Image hpBar;
// Start is called before the first frame update
void Start()
{
this.agent = this.GetComponent<NavMeshAgent>();
this.bossTrans = this.GetComponent<Transform>();
this.playerTrans = GameObject.FindWithTag("Player").GetComponent<Transform>();
this.anim = this.GetComponent<Animator>();
//agent.destination = this.playerTrans.position;
this.StartCoroutine(CheckMonsterState());
this.StartCoroutine(MonsterAction());
this.StartCoroutine(this.CoCheckTimeToLongAttack());
this.bodyMesh = GameObject.Find("BlackKnightMesh");
this.shieldMesh = GameObject.Find("ShieldMesh");
this.axeMesh = GameObject.Find("AxeMesh");
this.currHp = this.monsterHp;
hpBar = GameObject.FindGameObjectWithTag("HP_BAR")?.GetComponent<Image>();
}
private IEnumerator CoCheckTimeToLongAttack()
{
while (true)
{
this.time += Time.deltaTime;
if (time >= 3.2f)
{
this.ResetTime();
}
yield return null;
}
}
private void ResetTime()
{
this.time = 0;
}
private IEnumerator CheckMonsterState()
{
while (!isDie)
{
yield return new WaitForSeconds(0.3f);
if (this.state == eState.DIE) yield break;
float distance = Vector3.Distance(this.playerTrans.position, this.bossTrans.position);
if (distance <= closeAttackRange)
{
state = eState.ClOSE_ATTACK;
}
else if (distance <= longAttackRange&&this.time>=3.0f)
{
state = eState.LONG_ATTACK;
this.isThrow = false;
}
else if (distance <= traceRange)
{
state = eState.TRACE;
}
else
{
state = eState.IDLE;
}
}
}
private IEnumerator MonsterAction()
{
while (this.isDie == false)
{
switch (this.state)
{
case eState.IDLE:
this.Idle();
break;
case eState.ClOSE_ATTACK:
this.CloseAttack();
break;
case eState.TRACE:
this.Trace();
break;
case eState.LONG_ATTACK:
this.LongAttack();
break;
case eState.DIE:
this.Die();
break;
}
yield return new WaitForSeconds(0.3f);
}
}
private void Idle()
{
this.agent.isStopped = true;
this.anim.SetInteger(hashState,0);
}
private void CloseAttack()
{
this.anim.SetInteger(hashState, 2);
}
private void Trace()
{
this.agent.SetDestination(this.playerTrans.position);
this.agent.isStopped = false;
this.anim.SetInteger(hashState, 1);
}
private void LongAttack()
{
StartCoroutine(CoLongAttack());
}
private IEnumerator CoLongAttack()
{//투사체 던지기
this.anim.SetInteger(hashState, 3);
yield return new WaitForSeconds(0.2f);
Instantiate(this.SphereBomb, firePos.position, firePos.rotation);
Debug.Log("전");
yield return new WaitForSeconds(3.0f);
Debug.Log("후");
}
private void Die()
{
this.isDie = true;
this.agent.isStopped = true;
this.anim.SetTrigger("Die");
GetComponent<CapsuleCollider>().enabled = false;
Destroy(this.gameObject, 1.5f);
}
private void OnCollisionEnter(Collision collision)
{
if (currHp>0.0f&& collision.collider.CompareTag("Bullet"))
{
Destroy(collision.gameObject);
this.currHp -= 10.0f;
DisPlayHealth();
Debug.LogFormat("monsterhp:{0}", this.currHp);
if (this.currHp <= 0)
{
this.state = eState.DIE;
}
}
this.StartCoroutine(CoChangeMaterial());
}
private void DisPlayHealth()
{
hpBar.fillAmount = currHp / monsterHp;
}
private IEnumerator CoChangeMaterial()
{
this.bodyMesh.GetComponent<SkinnedMeshRenderer>().material = mat[0];
this.shieldMesh.GetComponent<MeshRenderer>().material = mat[0];
this.axeMesh.GetComponent<MeshRenderer>().material = mat[0];
yield return new WaitForSeconds(0.1f);
this.bodyMesh.GetComponent<SkinnedMeshRenderer>().material = mat[1];
this.shieldMesh.GetComponent<MeshRenderer>().material = mat[1];
this.axeMesh.GetComponent<MeshRenderer>().material = mat[1];
yield return null;
}
private void OnDrawGizmos()
{
if (state == eState.TRACE)
{
Gizmos.color = Color.blue;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.traceRange);
}
else if (state == eState.ClOSE_ATTACK)
{
Gizmos.color = Color.red;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.closeAttackRange);
}
else if (state == eState.LONG_ATTACK)
{
Gizmos.color = Color.yellow;
GizmosExtensions.DrawWireArc(this.transform.position, this.transform.forward, 360, this.longAttackRange);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SphereController : MonoBehaviour
{
[SerializeField]
private float force = 500f;
private Rigidbody rBody;
//[SerializeField]
//private GameObject bombPointGo;
// Start is called before the first frame update
void Start()
{
this.rBody = this.GetComponent<Rigidbody>();
this.rBody.AddForce(this.transform.forward * this.force);
}
private void OnCollisionEnter(Collision collision)
{
Destroy(this.gameObject);
Vector3 hitPoint = collision.GetContact(0).point;
//Instantiate(bombPointGo,hitPoint)
}
}
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using UnityEngine;
public class Player : MonoBehaviour
{
public Material[] mat = new Material[3];
[SerializeField]
private float moveSpeed = 4f;
[SerializeField]
private Animator anim;
private Rigidbody rBody;
[SerializeField]
private GameObject bossPrefab;
public System.Action onReachPortal;
//총알발사
[SerializeField]
private GameObject bulletPrefab;
[SerializeField]
private Transform firePos;
[SerializeField]
private GameObject fireFx;
private IEnumerator shootRoutine;
private GameObject bodyMesh;
private GameObject headMesh;
private void Start()
{
shootRoutine = CoFire();
this.rBody = this.GetComponent<Rigidbody>();
this.Idle();
this.bodyMesh = GameObject.Find("Body20");
this.headMesh = GameObject.Find("Head20");
}
// Start is called before the first frame update
public void Move(Vector3 dir)
{
this.rBody.isKinematic = false;
this.anim.SetInteger("State", 1);
//마우스 드래그 각도 구하기
var angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
var q = Quaternion.AngleAxis(angle, Vector3.up);
//마우스 각도만큼 회전시키고 그 방향으로(forward)이동하기
this.transform.rotation = q;
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
this.StopFire();
}
public void Idle()
{
//Debug.Log("idle");
this.anim.SetInteger("State", 0);
//this.rBody.isKinematic = true;
}
// 총 쏘는 자세
public void Attack()
{
if (this.bossPrefab != null)
{
this.anim.SetInteger("State", 2);
this.transform.LookAt(this.bossPrefab.transform.position);
this.Fire();
}
//조이스틱이 OnUp일때 Attack을 호출하니까 당연히 죽으면 바로 멈추는게 아니라 조이스틱을 한번 더 움직여야 멈춘다.
//else if(this.bossPrefab==null)
//{
// this.anim.SetInteger("State", 0);
// this.StopFire();
//}
}
//------------------------------------------------------총알 발사--------------------------------------------------------
public void Fire()
{
//Debug.Log("총알발사");
this.StartCoroutine(shootRoutine);
}
public void StopFire()
{
//Debug.Log("총알 발사 중지");
this.StopCoroutine(shootRoutine);
}
private IEnumerator CoFire()
{
while (true)
{
Instantiate(bulletPrefab, firePos.position, firePos.rotation);
this.ShowFireEffect();
yield return new WaitForSeconds(0.5f);
}
}
private void ShowFireEffect()
{
GameObject fireGo = Instantiate(fireFx, firePos.position, firePos.rotation);
Destroy(fireGo, 0.5f);
}
private void OnCollisionEnter(Collision collision)
{
this.StartCoroutine(CoChangeMaterial());
}
private IEnumerator CoChangeMaterial()
{
this.bodyMesh.GetComponent<SkinnedMeshRenderer>().material = mat[0];
this.headMesh.GetComponent<SkinnedMeshRenderer>().material = mat[0];
yield return new WaitForSeconds(0.1f);
this.bodyMesh.GetComponent<SkinnedMeshRenderer>().material = mat[1];
this.headMesh.GetComponent<SkinnedMeshRenderer>().material = mat[2];
//yield return null;
}
}



보스 애니메이터

집가서 할 거 - Player hp bar, 몬스터 죽으면 총쏘기 멈추기(idle)
카메라 좀 더 멀리 설정, 스카이 박스
시간 된다면 튜토리얼 연결하기
'3D 콘텐츠 제작' 카테고리의 다른 글
| 3D프로젝트 발표 (1) | 2023.10.12 |
|---|---|
| zombero-boss 전체 (0) | 2023.10.11 |
| zombero- boss (0) | 2023.10.10 |
| zombero-boss 3일 (0) | 2023.10.09 |
| zombero- boss 2일 (1) | 2023.10.08 |