Unity自学之旅04
Unity自学之旅④
📝 跳跃
public class PlayerBehaviorRigid : MonoBehaviour
{
//...
// 跳跃速度
public float JumpVelocity = 5f;
// 是否跳跃
private bool _isJumping;
void Start()
{
// 将当前player的刚体组件获取并设置
_rb = GetComponent<Rigidbody>();
}
void Update()
{
//...
// 按位或
_isJumping |= Input.GetKeyDown(KeyCode.J);
}
void FixedUpdate()
{
//...
if (_isJumping)
{
// 如果按下J键,瞬间力向上跳跃
_rb.AddForce(Vector3.up*JumpVelocity,ForceMode.Impulse);
}
_isJumping = false;
}
}
如何解决连续跳跃的问题,保证角色只可以进行一次跳跃。落地之后才可以接着进行跳跃。这个时候,需要使用一个遮罩层来完成。
Player会在场景中的Environment进行跳跃,也就是ground层,只需要计算Player与Ground层之间的距离,达到某个阈值视为触地。
public class PlayerBehaviorRigid : MonoBehaviour
{
// ...
// 跳跃速度
public float JumpVelocity = 5f;
// 是否跳跃
private bool _isJumping;
// 角色和地面之间的距离
public float DistanceToGround = 0.1f;
// Ground Layer 层
public LayerMask GroundLayer;
// 胶囊碰撞体
public CapsuleCollider _col;
void Start()
{
// 将当前player的刚体组件获取并设置
_rb = GetComponent<Rigidbody>();
// 获取当前角色的胶囊碰撞体
_col = GetComponent<CapsuleCollider>();
}
void Update()
{
// ...
// 按位或
_isJumping |= Input.GetKeyDown(KeyCode.J);
}
void FixedUpdate()
{
//...
if (IsGrounded() && _isJumping)
{
// 如果按下J键,瞬间力向上跳跃
_rb.AddForce(Vector3.up*JumpVelocity,ForceMode.Impulse);
}
_isJumping = false;
}
// 是否触地
private bool IsGrounded()
{
// 胶囊体的最底部位置 (碰撞器的中心坐标x,z,以及最小y轴坐标)
Vector3 capsuleBottom = new Vector3(_col.bounds.center.x,
_col.bounds.min.y, _col.bounds.center.z);
// 检查胶囊体中心到胶囊体底部之间的区域是否与地面层发生碰撞
// 距离如果小于 DistanceToGround 0.1f则视为碰撞触地
bool grounded = Physics.CheckCapsule(_col.bounds.center,
capsuleBottom,DistanceToGround,GroundLayer,QueryTriggerInteraction.Ignore);
return grounded;
}
}
🐯 攻击
遗漏了一个问题,给子弹添加RigidBody刚体组件
编写一个射击子弹的逻辑(在此之前,清除掉场景中的Bullet)
public class PlayerBehaviorRigid : MonoBehaviour
{
// ...
// 子弹GameObject
public GameObject Bullet;
// 子弹攻击速度
public float BulletSpeed = 100f;
// 是否攻击
public bool _isShooting;
void Start()
{
// 将当前player的刚体组件获取并设置
_rb = GetComponent<Rigidbody>();
// 获取当前角色的胶囊碰撞体
_col = GetComponent<CapsuleCollider>();
}
void Update()
{
//...
// 按下空格键 进行射击
_isShooting |= Input.GetKeyDown(KeyCode.Space);
}
void FixedUpdate()
{
//...
if (_isShooting)
{
// 每次空格键按下都会在Player的z轴前一个单位产生一颗子弹
GameObject newBullet = Instantiate(Bullet,this.transform.position
+new Vector3(0,0,1),this.transform.rotation) as GameObject;
Rigidbody BulletRb = newBullet.GetComponent<Rigidbody>();
// 直线射击子弹,子弹速度=player角色的面向方向*子弹速度
BulletRb.velocity = this.transform.forward * BulletSpeed;
}
_isShooting = false;
}
}
出现的新问题,子弹一直在创建新的对象,我们应该给其加入一个自动销毁策略,如:发射出三秒后销毁。为子弹添加一个脚本,3秒后销毁。
public class BulletBehavior : MonoBehaviour
{
public float OnScreenDelay = 3f;
void Start()
{
Destroy(this.gameObject, OnScreenDelay);
}
}
🦄 GUI
GUI前置,显示收集物品数量和角色Hp
创建一个管理类脚本,以及一个空对象,将管理类脚本挂载到空对象上。
public class GameBehavior : MonoBehaviour
{
private int _itemsCollected = 0;
private int _playerHp = 10;
public int Items
{
get { return _itemsCollected; }
set
{
_itemsCollected = value;
Debug.LogFormat("收集了:{0}",_itemsCollected);
}
}
public int HP
{
get { return _playerHp; }
set
{
_playerHp = value;
Debug.LogFormat("HP:{0}", _playerHp);
}
}
}
修改之前的逻辑,捡到Health_Pickup时给物品收集数量+1,然后运行游戏注意观察日志输出
public class ItemBehavior : MonoBehaviour
{
// 获取刚刚的GameManager脚本对象
public GameBehavior GameManager;
void Start()
{
GameManager = GameObject.Find("Game_Manager")
.GetComponent<GameBehavior>();
}
// 发生碰撞时被调用
void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.name == "Player")
{
// 销毁当前物体
Destroy(this.transform.gameObject);
Debug.Log("碰撞,销毁");
// 发生碰撞时意味着捡到了物品
GameManager.Items += 1;
}
}
}
UGUI
很简单,打开Inspect然后修改文字UI的位置以及字体颜色,运行观察一下效果
接着再绘制一个是否获胜的文字UI
编辑GameManager的脚本GameBehavior,很简单的逻辑,在项目启动时,赋予对应HP,Item初始的文字UI,然后当Item≥4时代表游戏获胜,将Progress设为win.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class GameBehavior : MonoBehaviour
{
private int _itemsCollected = 0;
public int Items
{
get { return _itemsCollected; }
set
{
_itemsCollected = value;
ItemsText.text = "Items Collected:" + Items;
Debug.LogFormat("收集了:{0}",_itemsCollected);
if(_itemsCollected >= MaxItems)
{
ProgressText.text = "win";
}
else
{
ProgressText.text = "Item found,only" + (MaxItems - _itemsCollected) + "more!";
}
}
}
private int _playerHp = 10;
public int HP
{
get { return _playerHp; }
set
{
_playerHp = value;
HealthText.text = "Player Health:" + HP;
Debug.LogFormat("HP:{0}", _playerHp);
}
}
// 游戏中一共存在四个可以收集的Health_pickup
public int MaxItems = 4;
// 三个UI文字
public TMP_Text HealthText;
public TMP_Text ItemsText;
public TMP_Text ProgressText;
void Start()
{
HealthText.text += _playerHp;
ItemsText.text += _itemsCollected;
}
}
光是文字的UI看着很low,或者说呈现方式并不是很好,现在改换思路,当游戏获胜时,弹出一个按钮之类的显示获胜。
绘制好了,然后默认情况下它不应该显示,将InSepct里面的复选框取消勾选,然后修改代码逻辑,当获胜时,显示该UI
记得在GameManager的脚步中将Button按钮挂载上去
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class GameBehavior : MonoBehaviour
{
//...
public int Items
{
get { return _itemsCollected; }
set
{
//...
if(_itemsCollected >= MaxItems)
{
//..
WinButton.gameObject.SetActive(true);
}
//...
}
}
//...
// 按钮UI
public Button WinButton;
//...
}
获胜了,但是还没有理想的效果,当获胜时,应该暂停游戏或者出现一个重新开始的功能,最主要的是当获胜时,我们应该停止角色的控制权限,不能再进行移动,跳跃,射击等功能。
游戏暂停和重新开始
游戏暂停:Time.timeScale = 0f;
时间流速设置为0,暂停游戏。当timeScale>=1
时,为正常时间流速。
游戏重新开始:一般通过重新加载第一个场景来完成,即SceneManager.LoadScene(0)
.
逻辑是,当获胜时暂停游戏,点击You Win
按钮时,重新开始游戏。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameBehavior : MonoBehaviour
{
//...
public int Items
{
get { return _itemsCollected; }
set
{
//...
if(_itemsCollected >= MaxItems)
{
//...
Time.timeScale = 0f;
}
//...
}
}
//...
// 重置场景
public void RestartScene()
{
SceneManager.LoadScene(0);
Time.timeScale = 1f;
}
}
需要注意的点:在Unity中不可以凭空运行,任何脚本都需要挂个GameObject来完成。
🤗 总结归纳
本文主要介绍了在 Unity 中实现角色跳跃、攻击以及游戏界面(GUI)相关功能的代码实现过程。包括解决角色连续跳跃问题、编写射击子弹逻辑并添加自动销毁策略、使用管理类脚本显示收集物品数量和角色 HP、通过 UGUI 修改文字 UI 以及绘制获胜按钮、实现游戏暂停和重新开始功能等。
重要亮点
- 角色跳跃功能实现:通过定义跳跃速度、是否跳跃等变量,在按下特定键时给角色添加向上的瞬间力实现跳跃。为解决连续跳跃问题,使用遮罩层计算角色与地面层之间的距离,只有落地后才能再次跳跃。
- 攻击功能实现:编写射击子弹的逻辑,按下特定键时在角色前方产生一颗子弹,并为子弹添加刚体组件和自动销毁策略,发射三秒后销毁。
- GUI 显示物品数量和 HP:创建管理类脚本,挂载到空对象上,实现收集物品数量和角色 HP 的显示。当角色捡到物品时,物品收集数量加一,并在日志中输出。
- UGUI 优化界面:通过修改文字 UI 的位置和字体颜色,绘制是否获胜的文字 UI。当物品收集数量达到一定值时,游戏获胜,显示 “win”,并可弹出按钮显示获胜。
- 游戏暂停和重新开始:当游戏获胜时,暂停游戏,时间流速设置为 0。点击获胜按钮可重新开始游戏,通过重新加载第一个场景实现,同时恢复时间流速为正常状态。
原文地址:https://blog.csdn.net/m0_63622279/article/details/145290035
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!