21.游戏场景-游戏主逻辑-小功能补充
21.1 知识点
现在子弹自动销毁不会播特效。在延迟执行的函数中调用死亡,让子弹销毁时波特小,效果更好。
private void DealyDestroy()
{
//直接执行死亡 会播放 特效
Dead();
}
//销毁场景上的子弹
public void Dead()
{
//创建死亡特效
GameObject effObj = Instantiate(Resources.Load<GameObject>(info.deadEffRes));
//设置特效的位置 创建在当前子弹的位置
effObj.transform.position = this.transform.position;
//1秒后延迟移除特效对象
Destroy(effObj, 1f);
//销毁子弹对象
Destroy(this.gameObject);
}
游戏场景的NGUI摄像机的EventSystem脚本中是默认隐藏鼠标的,要旋转取消勾选。
添加一个子弹层,给各个子弹预制体设置成子弹层。在PlayerObj脚本的Update检测中监听鼠标点击,发出射线碰撞到子弹则销毁子弹。
//射线检测 用于销毁子弹
if(Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo;
//这里只检测子弹层
if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000, 1 << LayerMask.NameToLayer("Bullet")))
{
BulletObject bulletObj = hitInfo.transform.GetComponent<BulletObject>();
//直接让被点中的子弹 销毁
bulletObj.Dead();
}
}
给游戏场景添加背景音乐。
21.2 知识点代码
BulletObject
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletObject : MonoBehaviour
{
//子弹使用的数据
private BulletInfo info;
//用于曲线移动的 计时变量
private float time;
//初始化子弹数据的方法
public void InitInfo(BulletInfo info)
{
this.info = info;
//根据生命周期函数 决定自己什么时候 延迟移除
//Destroy(this.gameObject, info.lifeTime);
Invoke("DealyDestroy", info.lifeTime);
}
private void DealyDestroy()
{
//直接执行死亡 会播放 特效
Dead();
}
//销毁场景上的子弹
public void Dead()
{
//创建死亡特效
GameObject effObj = Instantiate(Resources.Load<GameObject>(info.deadEffRes));
//设置特效的位置 创建在当前子弹的位置
effObj.transform.position = this.transform.position;
//1秒后延迟移除特效对象
Destroy(effObj, 1f);
//销毁子弹对象
Destroy(this.gameObject);
}
//和对象碰撞时(触发)
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.CompareTag("Player"))
{
//得到玩家脚本
PlayerObject obj = other.GetComponent<PlayerObject>();
//玩家受伤减血
obj.Wound();
//销毁自己
Dead();
}
}
void Update()
{
//所有移动的共同特点 都是朝自己的面朝向动
this.transform.Translate(Vector3.forward * info.forwardSpeed * Time.deltaTime);
//接着再来处理 其它的移动逻辑
//1 代表 只朝自己面朝向移动 直线运动
//2 代表 曲线运动
//3 代表 右抛物线
//4 代表 左抛物线
//5 代表 跟踪导弹
switch (info.type)
{
case 2:
time += Time.deltaTime;
//sin里面值变化的快慢 决定了 左右变化的频率
//乘以的速度 变化的大小 决定了 左右位移的多少
//曲线运动时 roundSpeed旋转速度 主要用于控制 变化的频率
this.transform.Translate(Vector3.right * Time.deltaTime * Mathf.Sin(time * info.roundSpeed) * info.rightSpeed);
break;
case 3:
//右抛物线 无非 就是 去改变 旋转角度
this.transform.rotation *= Quaternion.AngleAxis(info.roundSpeed * Time.deltaTime, Vector3.up);
break;
case 4:
//左抛物线 无非 就是 去改变 旋转角度
this.transform.rotation *= Quaternion.AngleAxis(-info.roundSpeed * Time.deltaTime, Vector3.up);
break;
case 5:
//跟踪移动 不停的计算 玩家和我之间的方向向量 然后得到四元数 然后自己的角度 不停的 变化为这个目标四元数
this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
Quaternion.LookRotation(PlayerObject.Instance.transform.position - this.transform.position),
info.roundSpeed * Time.deltaTime);
break;
}
}
}
PlayerObject
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerObject : MonoBehaviour
{
private static PlayerObject instance;
public static PlayerObject Instance => instance;
//血量
public int nowHp;
public int maxHp;
//速度
public int speed;
//旋转速度
public int roundSpeed;
//目标四元数角度
private Quaternion targetQ;
//是否死亡
public bool isDead;
//当前世界坐标转屏幕上的点
private Vector3 nowPos;
//上一次玩家的位置 就是在位移前 玩家的位置
private Vector3 frontPos;
private void Awake()
{
instance = this;
}
public void Dead()
{
isDead = true;
//显示游戏结束面板
GameOverPanel.Instance.ShowMe();
}
public void Wound()
{
if (isDead)
return;
//减血
this.nowHp -= 1;
//更新游戏面板上的血量显示
GamePanel.Instance.ChangeHp(this.nowHp);
//是否死亡了
if (this.nowHp <= 0)
this.Dead();
}
private float hValue;
private float vValue;
void Update()
{
//如果死亡了 没必要再移动了
if (isDead)
return;
//移动 旋转逻辑
//旋转
hValue = Input.GetAxisRaw("Horizontal");
vValue = Input.GetAxisRaw("Vertical");
//如果没有按我们的ad键 那么目标角度 就是000度
if (hValue == 0)
targetQ = Quaternion.identity;
//如果按ad键 就是 0020 或者00-20 根据你按的左右决定
else
targetQ = hValue < 0 ? Quaternion.AngleAxis(20, Vector3.forward) : Quaternion.AngleAxis(-20, Vector3.forward);
//让飞机朝着 这个目标四元数 去旋转
this.transform.rotation = Quaternion.Slerp(this.transform.rotation, targetQ, roundSpeed * Time.deltaTime);
//在位移之前 记录 之前的位置
frontPos = this.transform.position;
//移动
this.transform.Translate(Vector3.forward * vValue * speed * Time.deltaTime);
this.transform.Translate(Vector3.right * hValue * speed * Time.deltaTime, Space.World);
//进行极限判断
nowPos = Camera.main.WorldToScreenPoint(this.transform.position);
//左右 溢出判断
if( nowPos.x <= 0 || nowPos.x >= Screen.width )
{
this.transform.position = new Vector3(frontPos.x, this.transform.position.y, this.transform.position.z);
}
//上下 溢出判断
if( nowPos.y <= 0 || nowPos.y >= Screen.height )
{
this.transform.position = new Vector3(this.transform.position.x, this.transform.position.y, frontPos.z);
}
//射线检测 用于销毁子弹
if(Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo;
//这里只检测子弹层
if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000, 1 << LayerMask.NameToLayer("Bullet")))
{
BulletObject bulletObj = hitInfo.transform.GetComponent<BulletObject>();
//直接让被点中的子弹 销毁
bulletObj.Dead();
}
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com