0.按键配置相关
1.使用Input System配置,初始化相关将不作介绍,参考如下
2.配置如图
1.设计思路
1.通过PlayerManager控制Player的所有行为,将Player做成预制件PlayerPrefab方便死亡后对Player进行重新生成。
2.作为单例模式使用
private static PlayerController instance;
public static PlayerController Instance { get { return instance; } }
private void Awake()
{
instance = this;
}
2.速度切换
1.生成一个Sphere作为Player的子物体,设置它的Scale到比Player稍小,作为实际中弹的判定点,在Sphere Collider中同样勾选Is Trigger。
2.PlayerManager添加代码如下
AllActions actions;
Vector2 inputVec;
bool isLowSpeed;
Rigidbody rb;
float speed;
public float lowSpeed;
public float highSpeed;
GameObject hitBox;
private void Start()
{
rb = player.GetComponent<Rigidbody>();
actions.Player.LowSpeed.performed += LowMove;
//注册事件,长按Shift键时将速度设置为低速模式
actions.Player.LowSpeed.canceled += LowMoveOver;
//注册事件,松开Shift键时将速度恢复为高速模式
}
private void FixedUpdate()
{
Move();
}
private void Move()
{
inputVec = actions.Player.Move.ReadValue<Vector2>();
moveVec = player.transform.right * inputVec.x + player.transform.forward * inputVec.y;
//获取移动方向
rb.velocity = moveVec.normalized * speed;
//移动
}
private void LowMove(InputAction.CallbackContext obj)
{
isLowSpeed = true;
speed = lowSpeed;
hitBox.GetComponent<Renderer>().enabled = true;
//低速模式显示判定点
}
private void LowMoveOver(InputAction.CallbackContext obj)
{
isLowSpeed = false;
speed = highSpeed;
hitBox.GetComponent<Renderer>().enabled = false;
//高速模式不显示判定点
}
3.子弹射击与符卡释放
1.生成一个空物体命名为ShootPos作为Player的子物体,将其设置为Player的正前方
2.PlayerManager添加代码如下
bool isShoot;
public Transform shootPos;
GameObject bulletPrefab;
public float shootCD;
float shootTimer;
bool isBomb;
GameObject bombPrefab;
private void Start()
{
bulletPrefab = Resources.Load<GameObject>("Prefab/Bullet");
bombPrefab = Resources.Load<GameObject>("Prefab/Bomb");
actions.Player.Shoot.started += ShootStart;
//注册事件,按下Z键时开始射击
actions.Player.Shoot.canceled += ShootOver;
//注册事件,松开Z键时停止射击
actions.Player.Bomb.started += BombStart;
//注册事件,按下X键发射符卡
}
private void FixedUpdate()
{
Shoot();
}
private void Shoot()
{
shootTimer += Time.deltaTime;
if (shootTimer > shootCD)
//设置子弹射击间隔
{
if (isShoot)
{
shootTimer = 0;
Instantiate(bulletPrefab, shootPos.transform.position, Quaternion.identity);
}
}
}
private void ShootStart(InputAction.CallbackContext obj)
{
isShoot = true;
}
private void ShootOver(InputAction.CallbackContext obj)
{
isShoot = false;
}
private void BombStart(InputAction.CallbackContext obj)
{
isBomb = true;
StartCoroutine(Bomb());
}
public IEnumerator Bomb()
{
Instantiate(bombPrefab, new Vector3(10, 0, -50), Quaternion.identity);
yield return new WaitForSeconds(1);
Instantiate(bombPrefab, new Vector3(10, 0, -50), Quaternion.identity);
yield return new WaitForSeconds(0.5f);
Instantiate(bombPrefab, new Vector3(10, 0, -50), Quaternion.identity);
//克隆三次符卡预制件,实现全屏消弹
isBomb = false;
}
3.符卡身上的脚本
Rigidbody rb;
private void Start()
{
rb= GetComponent<Rigidbody>();
Destroy(gameObject, 4f);
}
private void Update()
{
rb.velocity = Vector3.forward*30;
}
private void OnTriggerStay(Collider other)
{
if (other.tag == "Bullet")
{
Destroy(other.gameObject);
}
}
4.擦弹实现
1.生成一个空物体命名为Graze作为Player的子物体,为其添加Sphere Collider,勾选Is Trigger,更改它的Radius比Player稍大,这里设置为3。
2.Graze添加代码如下
int graze;
private void OnTriggerExit(Collider other)
//此处使用OnTriggerExit是为了防止Player中弹也增加擦弹次数
{
if (other.tag == "Bullet")
{
graze+=1;
}
}
5.死亡相关
private void FixedUpdate()
{
deadTimer -= Time.deltaTime;
//计算无敌时间
if (deadTimer <= 0)
{
isInvincible = false;
}
}
public void PlayerDead()
//该函数在子弹脚本里调用
{
if (isInvincible == false)
{
if (isDead == false)
{
Destroy(player);
isDead = true;
isInvincible = true;
deadTimer = invincibleTime;
player = Instantiate(playerPrefab, new Vector3(10, 3, -50), Quaternion.identity);
InitPlayer();
}
}
}
private void PlayerRebirth(Transform player, Vector3 target, float duration)
{
player.DOMove(target, duration).OnComplete(PlayerRebirthOver);
//使用DoTween插件实现Player重生动画
}
private void PlayerRebirthOver()
{
isDead = false;
}