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”:
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);
}
}
4.添加射击效果GunParticles
我再这里用到GunParticles.由于要在枪口发射激光,我们把GunParticles效果粘贴到GunBarrelEnd,注意,并不是Player.
注意,不能直接把GunParticles拖到Hierarchy的GunBarrelEnd上!!
1).先选中GunParticles,在Particles System右上角选择 Copy Component
2)再在Hierarchy里选中GunBarrelEnd,在transform右上角选择Paste Component as new
3)成功添加,所以GunParticles效果会出现在枪的尾部
5.添加射击效果Line Renderer
设置Line Renderer参数:
7.添加射击时的Light
看到效果:
取消勾选Light和Particles,射击时我们才enable它
8.编写PlayerShooting.cs
注意:这是GunBarrelEnd的脚本,不是Player的!!
注意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可以被调用!