1.给Enemy添加EnemyHealth.cs

using UnityEngine;

public class EnemyHealth : MonoBehaviour
{
    public int startingHealth = 100;
    public int currentHealth;
    public float sinkSpeed = 2.5f;//Enemy死后的下沉速度
    public int scoreValue = 10;
    public AudioClip deathClip;//Enemy死后的发出的声音


    Animator anim;
    AudioSource enemyAudio;
    ParticleSystem hitParticles;
    CapsuleCollider capsuleCollider;
    bool isDead;
    bool isSinking;//Enemy死了会下沉,isSinking判断是否在下沉


    void Awake ()
    {
        anim = GetComponent <Animator> ();
        enemyAudio = GetComponent <AudioSource> ();
        hitParticles = GetComponentInChildren <ParticleSystem> ();
        capsuleCollider = GetComponent <CapsuleCollider> ();

        currentHealth = startingHealth;
    }


    void Update ()
    {
        if(isSinking)
        {
            transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
        }
    }


    public void TakeDamage (int amount, Vector3 hitPoint)
    {
        if(isDead)
            return;

        enemyAudio.Play ();

        currentHealth -= amount;
            
        hitParticles.transform.position = hitPoint;
        hitParticles.Play();

        if(currentHealth <= 0)
        {
            Death ();
        }
    }


    void Death ()
    {
        isDead = true;

        capsuleCollider.isTrigger = true;

        anim.SetTrigger ("Dead");

        enemyAudio.clip = deathClip;
        enemyAudio.Play ();
    }


    public void StartSinking ()
    {
        GetComponent <UnityEngine.AI.NavMeshAgent> ().enabled = false;
        GetComponent <Rigidbody> ().isKinematic = true;
        isSinking = true;
        //ScoreManager.score += scoreValue;
        Destroy (gameObject, 2f);
    }
}

注意几个API:

1)transform.Translate(Vector3 translation)

Vector3 translation的方向移动

transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime)

每次Update都向-Vector3.up移动sinkSpeed * Time.deltaTime的距离

在PlayerMovement.cs里使用的是:PlayerRigidbody.MovePosition(transform.position + movement);

MovePosition是直接移动到位置:transform.position + movement

2)

public void StartSinking ()
    {
        GetComponent<UnityEngine.AI.NavMeshAgent>().enabled = false;//把Enemy的NavMeshAgent关掉
        GetComponent<Rigidbody>().isKinematic = true;
        //Controls whether physics affects the rigidbody.
        //If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore.
        isSinking = true;
        Destroy(gameObject, 2f);//2秒后消除GameObject
    }

3)anim.SetTrigger ("Dead");

触发触发器“Dead”

对应EnemyAC中的其中一个参数“Dead”:

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

3.回到上一节给EnemyAttack.cs添加两行代码

using UnityEngine;
using System.Collections;

public class EnemyAttack : MonoBehaviour
{
    public float timeBetweenAttacks = 0.5f;
    public int attackDamage = 10;


    Animator anim;
    GameObject player;
    PlayerHealth playerHealth;
    EnemyHealth enemyHealth;
    bool playerInRange;
    float timer;


    void Awake ()
    {
        anim = GetComponent<Animator>();
        player = GameObject.FindGameObjectWithTag("Player");
        playerHealth = player.GetComponent<PlayerHealth>();
        playerInRange = false;
    }


    void OnTriggerEnter (Collider other)
    {
        
        if(other.gameObject == player)
        {
            playerInRange = true;
        }
    }


    void OnTriggerExit (Collider other)
    {
        if (other.gameObject == player)
        {
            playerInRange = false;
        }
    }


    void Update ()
    {
        timer += Time.deltaTime;
        if (timer>=timeBetweenAttacks&& playerInRange&& enemyHealth.currentHealth>0)
        {
            Attack();
        }
        if (playerHealth.currentHealth <= 0)
        {
            anim.SetTrigger("PlayerDead");
        }
    }


    void Attack ()
    {
        timer = 0f;
        if (playerHealth.currentHealth > 0)
            playerHealth.TakeDamage(attackDamage);
    }
}

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

4.添加射击效果GunParticles

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

我再这里用到GunParticles.由于要在枪口发射激光,我们把GunParticles效果粘贴到GunBarrelEnd,注意,并不是Player.

注意,不能直接把GunParticles拖到Hierarchy的GunBarrelEnd上!!

1).先选中GunParticles,在Particles System右上角选择 Copy Component

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

2)再在Hierarchy里选中GunBarrelEnd,在transform右上角选择Paste Component as new

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

3)成功添加,所以GunParticles效果会出现在枪的尾部

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

5.添加射击效果Line Renderer

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

设置Line Renderer参数:

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

7.添加射击时的Light

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

看到效果:

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

取消勾选Light和Particles,射击时我们才enable它

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

8.编写PlayerShooting.cs

注意:这是GunBarrelEnd的脚本,不是Player的!!

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

注意void shoot()这个函数

我们从枪口发射一条射线Ray,由两种可能,一是击中某样东西,二是什么都没击中。第二种情况我们会画一条很长的射线。

using UnityEngine;

public class PlayerShooting : MonoBehaviour
{
    public int damagePerShot = 20;
    public float timeBetweenBullets = 0.15f;//控制枪的射击速度
    public float range = 100f;//子弹能打多远


    float timer;
    Ray shootRay = new Ray();
    RaycastHit shootHit;//返回所击中的东西
    int shootableMask;//和FloorMask类似,只能射中标记为shootable的物体
    ParticleSystem gunParticles;
    LineRenderer gunLine;
    AudioSource gunAudio;
    Light gunLight;
    float effectsDisplayTime = 0.2f;//这些效果在消失之前的显示时间


    void Awake ()
    {
        shootableMask = LayerMask.GetMask ("Shootable");
        gunParticles = GetComponent<ParticleSystem> ();
        gunLine = GetComponent <LineRenderer> ();
        gunAudio = GetComponent<AudioSource> ();
        gunLight = GetComponent<Light> ();
    }


    void Update ()
    {
        timer += Time.deltaTime;

		if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets && Time.timeScale != 0)//("Fire1")指鼠标左键
        {
            Shoot ();
        }

        if(timer >= timeBetweenBullets * effectsDisplayTime)
        {
            DisableEffects ();
        }
    }


    public void DisableEffects ()
    {
        gunLine.enabled = false;
        gunLight.enabled = false;
    }


    void Shoot ()
    {
        timer = 0f;

        gunAudio.Play ();

        gunLight.enabled = true;

        gunParticles.Stop ();
        gunParticles.Play ();

        gunLine.enabled = true;
        gunLine.SetPosition (0, transform.position);//表示gunLine这条线0位置在枪管处

        shootRay.origin = transform.position;
        shootRay.direction = transform.forward;//transform.forward为z轴方向,即枪指的方向

        if (Physics.Raycast (shootRay, out shootHit, range, shootableMask))
        {
            EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
            if(enemyHealth != null)
            {
                enemyHealth.TakeDamage (damagePerShot, shootHit.point);
            }
            gunLine.SetPosition (1, shootHit.point);///表示gunLine这条线1位置在shootHit.point处
        }
        else
        {
            gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);///表示gunLine这条线1位置在离枪头100米处
        }
    }
}

LineRenderer.SetPosition()含义

9.保存Player这个Prefabs

由于我们把Player也设置为了一个Prefabs,记得按Apply,保存Player的所有更改,使得这个prefabs可以被调用!

Unity3d Survival Shooter Tutorial 学习笔记(六)---攻击敌人

相关文章:

  • 2021-07-05
  • 2021-03-30
  • 2022-12-23
  • 2022-12-23
  • 2021-09-06
  • 2022-12-23
  • 2022-01-14
  • 2021-08-07
猜你喜欢
  • 2021-06-01
  • 2022-12-23
  • 2021-08-30
  • 2021-08-14
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案