전체 코드
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;
[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;
}
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 BossMain : MonoBehaviour
{
[SerializeField]
private CJoystick1 joystick1;
[SerializeField]
private Player player;
private bool isDown;
// Start is called before the first frame update
void Start()
{
this.joystick1.onDown = () =>
{
this.isDown = true;
};
this.joystick1.onUp = () =>
{
this.isDown = false;
this.player.Attack();//아래에서 dir=vector3.zero 면 idle 실행하는거 썼는데 왜 여기다가 또 썼을까?
};
}
// Update is called once per frame
void Update()
{
//수평
var h = this.joystick1.Horizontal;
//수직
var v = this.joystick1.Vertical;
var dir = new Vector3(h, 0, v);
if (dir != Vector3.zero)
{
this.player.Move(dir);
}
//else if(dir==Vector3.zero&&isDown==false)
//this.player.Attack();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletController : MonoBehaviour
{
[SerializeField]
private float force = 1000f;
private Rigidbody rBody;
// Start is called before the first frame update
void Start()
{
this.rBody = this.GetComponent<Rigidbody>();
this.rBody.AddForce(this.transform.forward * this.force);
}
}
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using UnityEngine;
using UnityEngine.UI;
using static BossController;
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 float playerHp = 100.0f;
private float currHp;
private Image hpBar;
[SerializeField]
private Transform hpBarPos;
private void Start()
{
shootRoutine = CoFire();
this.rBody = this.GetComponent<Rigidbody>();
this.Idle();
this.bodyMesh = GameObject.Find("Body20");
this.headMesh = GameObject.Find("Head20");
this.currHp = this.playerHp;
hpBar = GameObject.FindGameObjectWithTag("HP_BAR2")?.GetComponent<Image>();
}
// 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();
this.hpBarPos.position = new Vector3(this.transform.position.x, this.transform.position.y + 2.4f, this.transform.position.z);
}
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);
}
//------------------------hp바-------------------------------------
private void OnCollisionEnter(Collision collision)
{
if (currHp > 0.0f && collision.collider.CompareTag("Bomb"))
{
this.currHp -= 20.0f;
DisPlayHealth();
}
this.StartCoroutine(CoChangeMaterial());
}
private void DisPlayHealth()
{
hpBar.fillAmount = currHp / playerHp;
hpBar.transform.position = this.hpBarPos.position;
}
//색 바꾸기 부딪히면
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];
}
}
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Animations;
public class FollowCamera : MonoBehaviour
{
public Transform targetTr;
private Transform cameraTr;
[Range(2.0f, 20.0f)]
public float distance = 8.0f;
[Range(10.0f, 20.0f)]
public float height = 15.0f;
// Start is called before the first frame update
void Start()
{
this.cameraTr = this.GetComponent<Transform>();
}
// Update is called once per frame
void LateUpdate()
{
this.cameraTr.position = new Vector3(6, height , targetTr.position.z- distance);
this.cameraTr.LookAt(targetTr.position);
this.cameraTr.rotation = Quaternion.Euler(27, 0, 0);
}
}
using UnityEngine;
public class GizmosExtensions
{
private GizmosExtensions() { }
/// <summary>
/// Draws a wire arc.
/// </summary>
/// <param name="position"></param>
/// <param name="dir">The direction from which the anglesRange is taken into account</param>
/// <param name="anglesRange">The angle range, in degrees.</param>
/// <param name="radius"></param>
/// <param name="maxSteps">How many steps to use to draw the arc.</param>
public static void DrawWireArc(Vector3 position, Vector3 dir, float anglesRange, float radius, float maxSteps = 20)
{
var srcAngles = GetAnglesFromDir(position, dir);
var initialPos = position;
var posA = initialPos;
var stepAngles = anglesRange / maxSteps;
var angle = srcAngles - anglesRange / 2;
for (var i = 0; i <= maxSteps; i++)
{
var rad = Mathf.Deg2Rad * angle;
var posB = initialPos;
posB += new Vector3(radius * Mathf.Cos(rad), 0, radius * Mathf.Sin(rad));
Gizmos.DrawLine(posA, posB);
angle += stepAngles;
posA = posB;
}
Gizmos.DrawLine(posA, initialPos);
}
static float GetAnglesFromDir(Vector3 position, Vector3 dir)
{
var forwardLimitPos = position + dir;
var srcAngles = Mathf.Rad2Deg * Mathf.Atan2(forwardLimitPos.z - position.z, forwardLimitPos.x - position.x);
return srcAngles;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RemoveBullet : MonoBehaviour
{
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.CompareTag("Bullet"))
{
Destroy(collision.gameObject);
Debug.Log("부딪힘");
}
}
}
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 UnityEngine;
using UnityEngine.EventSystems;
public class CJoystick1 : FloatingJoystick
{
public System.Action onDown;
public System.Action onUp;
// Start is called before the first frame update
protected override void Start()
{
base.Start();
//시작하면 조이스틱 비활성화 되는거 활성화하기
this.background.gameObject.SetActive(true);
}
//버튼(조이스틱) 누를때
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
this.onDown();
}
// 버튼에서 뗄때
public override void OnPointerUp(PointerEventData eventData)
{
base.OnPointerUp(eventData);
this.background.gameObject.SetActive(true);
//조이스틱 생성위치 anchore위치로 잡기(0,-722)/조이스틱 누르다가 떼면 제자리로 돌아가기
this.background.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -722f);
this.onUp();
}
}
'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 |