说明:玩家碰到尖刺或者被黑球撞到就会死亡
功能实现
尖刺碰撞
首先选中所有尖刺,为他们添加脚本Spike
using UnityEngine; public class Spike : MonoBehaviour { private void OnTriggerEnter(Collider other) { if (other.TryGetComponent(out PlayerController player)) { player.OnDefeated(); } } }
|
角色属性调整(关闭功能)
通过问题修复功能,自动在PlayerController脚本中生成**OnDefeated()**函数;
同样地,在input类中生成DisableGamePlayInputs();
public void OnDefeated() { input.DisableGamePlayInputs(); rigidBody.velocity = Vector3.zero; rigidBody.useGravity = false; rigidBody.detectCollisions = false; GetComponent<StateMachine>().SwitchState(typeof(PlayerState_Defeated)); }
|
DisableGamePlayInputs();只有一行代码:禁用当前输入动作表。playerInputAction.GamePlay.Disable();
小球碰撞
为球Ball添加脚本Ball,如果球撞到玩家,则执行玩家死亡游戏失败逻辑。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ball : MonoBehaviour { [SerializeField] Collider gameplayer; [SerializeField] PlayerController player; private void OnCollisionEnter(Collision other) { if (other.collider == gameplayer) { player.OnDefeated(); } } }
|
更简便的写法:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ball : MonoBehaviour { private void OnCollisionEnter(Collision other) { if (other.gameObject.TryGetComponent(out PlayerController player)) { player.OnDefeated(); } } }
|
给小球加上消失功能,大约6s摧毁自身
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ball : MonoBehaviour { [SerializeField] VoidEventChannel ballTriggeredEventChannel; private void OnEnable() { ballTriggeredEventChannel.AddListener(EliminateBall); } private void OnDisable() { ballTriggeredEventChannel.RemoveListener(EliminateBall); } private void OnCollisionEnter(Collision other) { if (other.gameObject.TryGetComponent(out PlayerController player)) { player.OnDefeated(); } } private void EliminateBall() { Destroy(gameObject, 6f); } }
|
对状态的操作
新建状态PlayerState_Defeated
用来玩家生成死亡时的音效、特效
using System; using UnityEngine; [CreateAssetMenu(menuName = "Data/StateMachine/PlayerState/Defeated", fileName = "PlayerState_Defeated")] public class PlayerState_Defeated : PlayerState { [SerializeField] ParticleSystem Deathvfx; [SerializeField] AudioClip[] voice; public override void Enter() { base.Enter(); Instantiate(Deathvfx, player.transform.position, Quaternion.identity); AudioClip deathVoice = voice[UnityEngine.Random.Range(0, voice.Length)]; player.voicePlayer.PlayOneShot(deathVoice); } }
|
UI相关
新建SceneLoader脚本用来管理场景的切换,用来实现ui中按钮功能
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class SceneLoader { public static void ReloadScene() { int sceneIndex = SceneManager.GetActiveScene().buildIndex; SceneManager.LoadScene(sceneIndex); } public static void QuitGame() { #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #else Application.Quie(); #endif } public static void LoadNextScene() { int sceneIndex = SceneManager.GetActiveScene().buildIndex + 1; if (sceneIndex >= SceneManager.sceneCount) { ReloadScene(); return; } SceneManager.LoadScene(sceneIndex); } }
|
UI中新建DefeatScreen同名脚本
OnEnable和OnDisable中订阅、退订按钮功能。
PlayerShot中实现随机播放失败bgm。这里有个问题,我在玩家失败状态类中实现这个功能的时候,最终运行时音效呈现的效果是若干音乐叠加 而且音调更低,排查了很久找不到原因,所以我把这个功能改成了动画事件触发。动画里事件大概在这个位置
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class DefeatScreen : MonoBehaviour { [SerializeField] VoidEventChannel playerDefeatedEventChannel; [SerializeField] AudioClip[] voice; [SerializeField] Button retryButton; [SerializeField] Button quitButton; private void OnEnable() { playerDefeatedEventChannel.AddListener(ShowUI); retryButton.onClick.AddListener(SceneLoader.ReloadScene); quitButton.onClick.AddListener(SceneLoader.QuitGame); } private void OnDisable() { playerDefeatedEventChannel.RemoveListener(ShowUI); retryButton.onClick.RemoveListener(SceneLoader.ReloadScene); quitButton.onClick.RemoveListener(SceneLoader.QuitGame); } private void ShowUI() { GetComponent<Canvas>().enabled = true; GetComponent<Animator>().enabled = true; Cursor.lockState = CursorLockMode.None; } void PlayerShot() { AudioClip retryVoice = voice[UnityEngine.Random.Range(0, voice.Length)]; SoundEffectsPlayer.audioSource.PlayOneShot(retryVoice); } }
|