본문 바로가기
3D 콘텐츠 제작

zombero-boss 전체

by 노재두내 2023. 10. 11.

전체 코드

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