Zombie.ts

Zepeto 2022. 3. 31. 00:32
반응형
import { ZepetoScriptBehaviour } from "ZEPETO.Script";
import {
  Vector3,
  Transform,
  Coroutine,
  Animator,
  WaitForSeconds,
  Time,
  Mathf,
  Quaternion,
  CapsuleCollider,
  Object,
  GameObject,
  SkinnedMeshRenderer,
  Color,
  Random,
} from "UnityEngine";
import { Slider } from "UnityEngine.UI";
import { NavMesh, NavMeshAgent, NavMeshHit } from "UnityEngine.AI";
import { isForInStatement } from "typescript";
import RaycastPerception3D from "./RaycastPerception3D";
import { UnityEvent$1, UnityEvent } from "UnityEngine.Events";

export default class Zombie extends ZepetoScriptBehaviour {
  //public target: GameObject;
  
  public  slider : Slider;
  public agent: NavMeshAgent;
  private routine: Coroutine;
  private anim: Animator;
  private moveTargetPosition: Vector3;
  public maxHp: float;
  public hp: float;
  public dieEvent: UnityEvent;
  public attackEvent : UnityEvent;

  private rayPerception3D: RaycastPerception3D;

  public Init(initPos: Vector3, initHp: float) {

    this.dieEvent = new UnityEvent();
    this.attackEvent = new UnityEvent();
    
    //this.target = target;
    this.transform.position = initPos;
    this.maxHp = initHp;
    this.hp = this.maxHp;
    //console.log(this.target);
    this.agent = this.GetComponent<NavMeshAgent>();
    this.anim = this.GetComponent<Animator>();
    //console.log(this.agent);

    var renderer =
      this.gameObject.GetComponentInChildren<SkinnedMeshRenderer>();

    this.rayPerception3D = this.GetComponent<RaycastPerception3D>();
    this.rayPerception3D.Init();
    this.rayPerception3D.AddTag("Player");
    // console.log("rayPerception3D ---> " + this.rayPerception3D);
    // console.log(
    //   "rayPerception3D.triggerTargetEvent ---> " +
    //     this.rayPerception3D.triggerTargetEvent
    // );
    this.rayPerception3D.triggerTargetEvent.AddListener((target) => {
      // console.log("target: " + target);
      if (target != null) {
        var dis = Vector3.Distance(
          target.transform.position,
          this.transform.position
        );

        if (dis <= 1.1) {
          var state = this.anim.GetInteger("State");
          
          //console.log("state---->" + state);
          
          if (state != 2) {
            //공격 상태라면 패스
            this.MoveStop(); //멈추고
            this.transform.LookAt(target.transform); //바라보고
            // console.log("attack!");
            
            this.anim.speed = 4;
            
            this.anim.SetInteger("State", 2); //공격 애니메이션
            //this.anim.Play("zombie_attack", -1, 0); //리셋 애니메이션 그리고 플레이
            if (this.routine != null) this.StopCoroutine(this.routine);
            //그리고 잠시후 Idle
            this.routine = this.StartCoroutine(this.WaitForAttack());
          }else{

            // console.log("state---->" + state);
            
          }
        } else {
          this.Move(target.transform.position);
        }
      } else {
        //target is null
        this.MoveAny();
      }
    });
  }

  *WaitForAttack() {
    //공격 속도 4배 하면 0.412
    
    yield new WaitForSeconds(0.65/this.anim.speed); //1배속일때 0.65
    
    this.attackEvent.Invoke();
    
    yield new WaitForSeconds(1.0/this.anim.speed);
    this.anim.speed = 1;
    this.anim.SetInteger("State", 0);
    //console.log('attack complete');
  }

  public MoveAny() {
    var tpos: Vector3 = this.RandomNavSphere(20);
    this.Move(tpos);
  }

  // public FindTarget() {
  //   var players = GameObject.FindGameObjectsWithTag("Player");
  //   console.log(`[FindTarget] : players : ${players.length}`);

  //   var min = 1000000;
  //   var newTarget = null;
  //   for (var i = 0; i < players.length; i++) {
  //     var player = players[i];
  //     var dis = Vector3.Distance(
  //       player.transform.position,
  //       this.transform.position
  //     );
  //     if (min > dis) {
  //       min = dis;
  //       newTarget = player.transform;
  //     }
  //   }

  //   if (newTarget != null) {
  //     console.log(`nearest target: ${newTarget.name}`);
  //   } else {
  //     console.log("target is null...");
  //   }

  //   return newTarget;
  // }

  public IsDie() {
    return this.hp <= 0;
  }

  public Move(tpos) {
    this.agent.ResetPath();
    this.agent.isStopped = false;
    this.agent.updatePosition = true;
    this.agent.updateRotation = true;
    this.agent.speed = 1;

    this.transform.LookAt(tpos);
    this.agent.SetDestination(tpos);
    if (this.routine != null) this.StopCoroutine(this.routine);
    this.routine = this.StartCoroutine(
      this.MoveRoutine(tpos, () => {
        // check distance
      })
    );

    // this.NavigateStart();
    // this.moveTargetPosition = this.target.position;
    // //this.anim.Play("zombie_walk_forward");
    // this.anim.SetInteger("State", 1);
    // this.agent.SetDestination(this.moveTargetPosition);
    // if (this.routiune != null) this.StopCoroutine(this.routiune);
    // this.routiune = this.StartCoroutine(
    //   this.MoveRoutine((nearTarget) => {
    //     console.log(`nearTarget: ${nearTarget}`);
    //     if (nearTarget) {
    //       this.Attack();
    //     } else {
    //       console.log("----------------- idle -----------------");
    //       this.NavigateStop();
    //       this.anim.SetInteger("State", 0);
    //       //this.anim.Play("zombie_idle");
    //       // //this.Invoke("Move", 1.5);
    //       this.StartCoroutine(this.WaitForMove(1.5));
    //     }
    //   })
    // );
  }

  // *WaitForMove(sec: float) {
  //   yield new WaitForSeconds(sec);
  //   this.Move();
  // }

  public MoveStop() {
    this.anim.speed = 1.0;
    this.agent.ResetPath();
    this.agent.isStopped = true;
    this.agent.updatePosition = false;
    this.agent.updateRotation = false;
    this.agent.velocity = Vector3.zero;
    this.agent.speed = 0;
  }

  public Hit(damage: float) {
    
    if(this.IsDie()) return;
    
    this.hp -= damage;
    
    //console.log(this.hp + " / " + this.maxHp);

    if (this.hp <= 0) {
      this.hp = 0;
      this.UpdateHpGauge();
      this.rayPerception3D.enabled = false;
      if (this.routine != null) this.StopCoroutine(this.routine);
      this.MoveStop();
      this.GetComponent<CapsuleCollider>().enabled = false;
      this.anim.SetTrigger("Dead");
      this.StartCoroutine(this.DieRoutine());
    }else{
      this.UpdateHpGauge();
    }
  }
  
  UpdateHpGauge()
  {
    var per = this.hp / this.maxHp;
    console.log(per);
    this.slider.value = per;
  }

  *DieRoutine() {
    yield new WaitForSeconds(1.6);
    //this.dieEvent.Invoke();
    
    this.StopAllCoroutines();
    
    Object.Destroy(this.gameObject);
  }

  public Attack(target) {
    
    
    // console.log(
    //   `[Attack] target: ${target}, ${target.name}, ${target.position}`
    // );
    //사거리 체크
    var dis = Vector3.Distance(
      target.transform.position,
      this.transform.position
    );

    //console.log(dis);

    if (dis <= 1.1) {
    } else if (dis < 3) {
    } else {
      //너무 멀면 아무대나로 이동
      var tpos: Vector3 = this.RandomNavSphere(20);
      this.Move(tpos);
    }

    //방법 2
    // var dir: Vector3 = this.target.position - this.transform.position;
    // var angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
    // this.transform.rotation = Quaternion.AngleAxis(angle, Vector3.up);

    //방법 3
    // var relative: Vector3 = this.transform.InverseTransformPoint(
    //   this.target.position
    // );
    // var angle = Mathf.Atan2(relative.x, relative.z) * Mathf.Rad2Deg;
    // this.transform.Rotate(new Vector3(0, angle, 0));

    //this.anim.Play("zombie_attack", -1, 0); //reset anim
    // this.anim.SetInteger("State", 2);

    // if (this.routiune != null) this.StopCoroutine(this.routiune);

    // this.routiune = this.StartCoroutine(
    //   this.AttackRoutine(() => {
    //     console.log("attack complete!");
    //     //this.anim.Play("zombie_idle", -1, 0); //reset anim
    //     //this.Move();
    //     this.anim.SetInteger("State", 0);
    //     //this.anim.Play("zombie_idle", -1, 0); //reset anim

    //     //find target
    //     var playerGo = GameObject.FindGameObjectWithTag("Player");
    //     var dis = Vector3.Distance(
    //       playerGo.transform.position,
    //       this.transform.position
    //     );
    //     if (dis <= 1.1) {
    //       this.StartCoroutine(this.WaitForAttackDelay(0.5));
    //     } else {
    //       this.Move();
    //     }
    //   })
    // );
  }

  *MoveRoutine(tpos, callback) {
    
    this.anim.speed = 5;
    
    this.anim.SetInteger("State", 1);

    while (true) {
      var dis: float = Vector3.Distance(tpos, this.transform.position);
      //console.log(dis);
      if (dis <= 1.1) {
        break;
      }
      yield null;
    }

    this.anim.SetInteger("State", 0);
    this.MoveStop();
    //console.log("----------> move complete");

    callback();
  }

  RandomNavSphere(dist: float) {
    var dir = Random.insideUnitSphere;
    dir.x *= dist;
    dir.y *= dist;
    dir.z *= dist;

    let hit = $ref<NavMeshHit>();
    NavMesh.SamplePosition(dir, hit, dist, 1);

    return $unref(hit).position;
  }

  // *WaitForAttackDelay(delay: float) {
  //   yield new WaitForSeconds(delay);
  //   this.Attack();
  // }

  *AttackRoutine(callback) {
    yield new WaitForSeconds(1.5);
    callback();
  }

  //이동중 언제라도 타겟을 공격할수 있는 사거리라면 즉시 공격한다
  // *MoveRoutine(callback) {
  //   var nearTarget: bool;
  //   while (true) {
  //     if (this.target == null) break;

  //     var dis = Vector3.Distance(
  //       this.transform.position,
  //       this.moveTargetPosition
  //     );

  //     var dis2 = Vector3.Distance(
  //       this.transform.position,
  //       this.target.position
  //     );

  //     if (dis2 <= 1.1) {
  //       nearTarget = true;
  //       break;
  //     }

  //     //   console.log(dis);
  //     if (dis <= 1.1) {
  //       if (dis2 <= 1.1) {
  //         nearTarget = true;
  //       } else {
  //         nearTarget = false;
  //       }
  //       break;
  //     }
  //     yield null;
  //   }

  //   console.log("move complete");

  //   callback(nearTarget);
  // }

  private extraRotSpeed = 5.0;

  Update() {
    // var lookRotation: Vector3 =
    //   this.agent.steeringTarget - this.transform.position;
    // this.transform.rotation = Quaternion.Slerp(
    //   this.transform.rotation,
    //   Quaternion.LookRotation(lookRotation),
    //   this.extraRotSpeed * Time.deltaTime
    // );
  }
}
반응형

'Zepeto' 카테고리의 다른 글

제페토 월드 만들기 (회전 동기화)  (0) 2022.04.11
찰칵  (0) 2022.03.31
zepeto world orientation horizontal  (0) 2022.03.25
zepeto-multiplay-example  (0) 2022.03.25
zepeto-script-sample  (0) 2022.03.25
: