在Unity中创建篮球游戏应用:第2部分


文档摘要

在Unity中创建篮球游戏应用:第2部分 前提条件 Unity 此活动要求您在Unity中创建一个应用。如果您尚未安装Unity,请访问unity.com/download下载Unity Hub。此活动可以使用Unity版本2020.3.20f1或更高版本完成。 Visual Studio 此活动要求您在Visual Studio中编写代码。请确保已安装Visual Studio,并将其设置为Unity的默认脚本编辑器。如果您不熟悉如何将Visual Studio设置为默认编辑器,请查阅设置您的默认脚本编辑器。此活动可以使用Visual Studio 2019或更高版本完成。 第6单元活动项目 此活动从第6单元活动结束的地方开始。如果您尚未完成该活动,请下载并打开第6单元活动项目中的项目。

在Unity中创建篮球游戏应用:第2部分

前提条件

Unity

此活动要求您在Unity中创建一个应用。如果您尚未安装Unity,请访问unity.com/download下载Unity Hub。此活动可以使用Unity版本2020.3.20f1或更高版本完成。

Visual Studio

此活动要求您在Visual Studio中编写代码。请确保已安装Visual Studio,并将其设置为Unity的默认脚本编辑器。如果您不熟悉如何将Visual Studio设置为默认编辑器,请查阅设置您的默认脚本编辑器。此活动可以使用Visual Studio 2019或更高版本完成。

第6单元活动项目

此活动从第6单元活动结束的地方开始。如果您尚未完成该活动,请下载并打开第6单元活动项目中的项目。

指示

在这个活动中,您将为篮球游戏创建游戏玩法功能。

创建玩家移动

为了这个原型,您将使用键盘输入来模拟玩家移动。左箭头和右箭头键应分别使玩家向左和向右移动。

  1. 创建一个脚本,以便您可以根据箭头键的方向移动玩家。在项目窗口中,右键点击进入脚本文件夹,选择创建 > C# 脚本。将脚本命名为PlayerControls,双击以编译并在Visual Studio中打开。

    创建脚本的菜单截图

  2. 在Visual Studio中,添加以下脚本并保存(稍后提供解释):

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerControls : MonoBehaviour { public float moveSpeed = 5; // Start is called before the first frame update void Start() { } void Update() { //Creating a direction vector based on the input axes (X being Horizontal direction, Y being 0 as we do not want the player to move beyond the plane and Z being Vertical direction). Vector3 direction = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")); //Change the position transform by the direction vector times the preset movement speed and the time. transform.position += direction * moveSpeed * Time.deltaTime; //Makes the character look towards the vector's direction. transform.LookAt(transform.position + direction); } }
  3. 在Unity编辑器中,将PlayerControls脚本作为组件添加到玩家上。可以通过将脚本拖放到玩家游戏对象上来实现这一点。您可以通过查看检查器窗口中的玩家游戏对象来验证脚本是否已成为组件。

    添加玩家移动脚本的截图

  4. 按下播放按钮测试脚本。

    • 右箭头键使玩家向右移动。
    • 左箭头键使玩家向左移动。
    • 上箭头键使玩家向前移动。
    • 下箭头键使玩家向后移动。

    播放模式截图

创建球员球位

当游戏开始时,篮球放置在玩家前方的一个持球位置。为此创建一个持球位置。

  1. 层级窗口中,选择玩家。右键点击并选择创建空对象。将其命名为HoldPos

    创建空游戏对象的截图

  2. HoldPos应该位于玩家前方约手臂高度的位置(略高于玩家的一半高度)。修改HoldPos 变换位置0, 0.2, 1.2。这将HoldPos定位在玩家前方并稍微向上。

    持球位置对象变换的截图

  3. 使用代码,在游戏开始时将篮球放置在HoldPos。在Visual Studio中,向PlayerControls脚本添加GameObject variable for the basketball and a Transform variable for the position of HoldPos

    public GameObject basketball; public Transform holdPos;

    这将在游戏开始时将篮球放置在HoldPos上:

    void Start() { basketball.transform.position = holdPos.position; }
  4. 在Unity编辑器中,展开玩家控制脚本组件上的玩家。将篮球游戏对象拖到篮球字段中。同时,将HoldPos游戏对象拖到持球位置字段中。

    玩家控制脚本属性的截图

  5. 按下播放按钮测试脚本。当场景开始时,篮球会被定位在HoldPos上。

将球举过头顶

在玩家可以投篮之前,他们必须将球举过头顶。这确保了球被保持在一个理想的投篮弧度高度。由于玩家只有在球没有飞向篮筐时才能持球,因此您需要创建布尔逻辑来处理球的状态。创建一个球的举过头顶位置,并添加一个检查球是否被玩家持有的条件语句。如果玩家正在持球,则使用空格键将球举过头顶。

  1. 层级窗口中,选择玩家。右键点击并选择创建空对象。将其命名为OverheadPos

    创建空游戏对象的截图

  2. OverheadPos应位于玩家前方并略微高于其头部的位置。修改OverheadPos 变换位置0, 0.5, 1.2。这将OverheadPos定位在玩家前方并稍微高于其头部。

    举过头顶位置变换的截图

  3. PlayerControls脚本中,创建一个Transform variable for the position of OverheadPos

    public Transform overheadPos;
  4. 接下来,创建两个布尔(真/假)变量,定义球是否在玩家手中或飞向篮筐。

    //Our game will start with the ball in the character's hand, thus the assigned value is true. private bool isBallInHands = true; private bool isBallFlying = false;

    游戏开始时,篮球玩家手中。因此,在游戏开始时,isBallInHands is true and isBallFlying is false.

  5. Next, add a conditional statement that checks whether the ball is being held by the Player. If the ball is in their possession, then pressing the space bar on the keyboard will raise the ball to the OverheadPos. Add the following conditional statement below in the Update()方法在玩家移动控制之后:

    if (isBallInHands) { //If it is, we will define the space key as the key to hold the ball over the character's head. if (Input.GetKey(KeyCode.Space)) { basketball.transform.position = overheadPos.position; } else { basketball.transform.position = holdPos.position; } }
  6. 在Unity编辑器中,展开玩家控制脚本组件上的玩家。将HoldPos游戏对象拖到举过头顶位置字段中。

    玩家控制脚本属性的截图

  7. 按下播放按钮测试脚本。按下空格键篮球举起。

投篮

一旦球被放在玩家头顶上方,玩家就可以投篮。玩家瞄准目标(实际上是篮球篮筐)。当空格键被释放时,球被认为已经被投出。创建一个目标位置的游戏对象,并添加一个检查空格键是否被释放的条件语句。如果空格键被释放,则投篮。

  1. 层级窗口中,选择篮球篮筐。右键点击并选择创建空对象。将其命名为TargetPos

    创建空游戏对象的截图

  2. TargetPos应位于篮筐前方。修改TargetPos 变换位置为**-0.4, 12, -2.4**。这将TargetPos定位在篮球篮筐的篮筐处。

    目标位置变换的截图

  3. PlayerControls脚本中,创建一个Transform variable for the TargetPos and a float variable for the length of time that the basketball在空中。

    public Transform targetPos; private float T = 0;
  4. if (isBallInHands) statement modify the statement to include the transform.LookAt()方法中:

    if (isBallInHands) { //If it is, we will define the space key as the key to hold the ball over the character's head. if (Input.GetKey(KeyCode.Space)) { basketball.transform.position = overheadPos.position; transform.LookAt(targetPos.parent.position); } else { basketball.transform.position = holdPos.position; } }

    transform.LookAt() method faces the Player in the direction of the basketball-hoop.

  5. Add another conditional statement within the if (isBallInHands)语句检查空格键是否被释放:

    if (Input.GetKeyUp(KeyCode.Space)) { //For the ball to be shot, it must leave the character hands, so we make the boolean variable false. isBallInHands = false; //To begin shooting, we change the boolean flying to true (as the ball starts flying from the hands) isBallFlying = true; //And restart the time (so that the new series of events can be easily written) T = 0; }
  6. 下一步是添加球被投出后的效果。一旦球被投出,程序使用两个向量点(TargetPoint and OverHeadPos) to determine the direction of the basketball. A new vector is created from these vectors and the basketball position is changed accordingly. Add the following conditional statement after the if (isBallInHands)语句。

    if (isBallFlying) { //Time variable is assigned a new value based on the time the event starts T += Time.deltaTime; //duration of travel float duration = 0.5f; //This variable allows for the interpolation to be accurate, as we want a set duration for the shooting. float t01 = T / duration; Vector3 point_A = overheadPos.position; Vector3 point_B = targetPos.position; //Lerp is the linear interpolation function, will result in a new vector that will represent the trajectory from A to B. Vector3 pos = Vector3.Lerp(point_A, point_B, t01); }
  7. 为了以真实的方式投篮,您可以创建一个弧线并将其添加到basketball position once shot. Add the following in the if (isBallFlying)语句:

    //Arc created using sine function Vector3 arc = Vector3.up * 5 * Mathf.Sin(t01 * 3.14f); //Moves the ball in an arc function basketball.transform.position = pos + arc;
  8. 在Unity编辑器中,展开玩家控制脚本组件上的玩家。将TargetPos游戏对象拖到目标位置字段中。同时,将HoldPos游戏对象拖到持球位置字段中。

    玩家控制脚本属性的截图

  9. 按下播放按钮测试脚本。按下并释放空格键投篮。注意虽然篮球以弧线射向TargetPos,但篮球在空中会持续上下弹跳。您可以添加物理效果来解决这个问题。

为篮球添加物理效果

物理效果对于球在空中运动时的行为至关重要。通常,当篮球被投出时,球也会在地面上滚动。为篮球添加一个刚体组件,使所需的物理效果能够实现。

  1. 层级中,选择篮球并添加一个刚体组件。

    向篮球游戏对象添加刚体组件的截图

  2. 您将在PlayerControls脚本中操纵对象的物理效果。因此勾选Is Kinematic复选框。如果启用了Is Kinematic,则对象不受物理引擎驱动,只能通过其变换来操作。

    篮球游戏对象属性的截图

  3. PlayerControls脚本中,在if (isBallFlying)语句的末尾添加以下内容:

    if (t01 >= 1) { isBallFlying = false; basketball.GetComponent<Rigidbody>().isKinematic = false; }

为篮球添加碰撞器

目前,投篮后的篮球会穿过球场。碰撞器会在球周围创建一个看不见的网格,从而使球与球场发生碰撞。为篮球添加一个球形碰撞器。

  1. 层级中,选择篮球并添加一个球形碰撞器组件。

    篮球游戏对象属性的截图

  2. 现在篮球已经有了碰撞器,需要调整碰撞器大小以适应球的形状。在球形碰撞器属性中,选择编辑碰撞器并调整碰撞器大小。

    篮球刚体属性的截图

  3. 按下播放按钮测试更改。投篮后,篮球会落到地上并停留在原地。

拾起球

投篮后,篮球会落在球场上并停留在原地。玩家应该收回篮球以便再次投篮。使用代码,创建逻辑让玩家在投篮后收回篮球。

  1. Player Controls脚本中,在if (isBallFlying) statement and outside of the Update()方法之后添加以下内容:

    //when the collision trigger happens, this method is executed. private void OnTriggerEnter(Collider other) { //Conditional: If the ball isn't flying or has not been picked up yet, pick up the ball and activate its Rigidbody component's kinematics. if (!isBallInHands && !isBallFlying) { isBallInHands = true; basketball.GetComponent<Rigidbody>().isKinematic = true; }
  2. 层级中,选择玩家。现在在检查器中,转到对象的盒状碰撞器并点击isTrigger复选框。

    玩家对象属性的截图

  3. 按下播放按钮试玩游戏。投篮后,篮球返回到HoldPos并准备再次投篮。随着玩家在球场上移动,玩家在投篮前会调整朝向篮球篮筐

    玩家对象投篮篮球的截图

解决方案

要查看此活动的项目样本,请导入XR开发入门存储库中的第7单元作业Unity包。

如何将包导入Unity

  1. 在顶部导航菜单中,选择资产 > 导入包 > 自定义包
  2. 导入Unity包窗口中,选择全部然后导入
  3. 一旦包被导入,打开Unit-7场景。

声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。


发布者: 作者: 转发
评论区 (0)
U