Unity 的 RTS 和 MOBA 玩家控制器
在视频游戏中,RTS 一词代表实时策略。
RTS 与传统第一人称/第三人称射击游戏的区别在于,角色是使用鼠标指针控制的,而不是通常的 W、A、S 和 D 按钮。
玩家可以鸟瞰战场,能够向部队下达命令,但无需直接控制他们。RTS 游戏的示例有《魔兽争霸》、《星际争霸》、《哥萨克》等。
另一方面,MOBA 代表多人在线战斗竞技场,它是 RTS 游戏的一种较新的子类型,玩家仅控制一个角色而不是多个角色。
此类游戏的例子有《英雄联盟》和《Dota 2》。
在本教程中,我将展示如何在 Unity 中创建 RTS/MOBA 风格的控制器。
第 1 步:让我们创建必要的脚本
本教程非常简单,因为它只需要一个脚本。
RTSPlayerController.cs
//You are free to use this script in Free or Commercial projects
//sharpcoderblog.com @2018
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class RTSPlayerController : MonoBehaviour
{
public Camera playerCamera;
public Vector3 cameraOffset;
public GameObject targetIndicatorPrefab;
NavMeshAgent agent;
GameObject targetObject;
// Use this for initialization
void Start()
{
agent = GetComponent<NavMeshAgent>();
//Instantiate click target prefab
if (targetIndicatorPrefab)
{
targetObject = Instantiate(targetIndicatorPrefab, Vector3.zero, Quaternion.identity) as GameObject;
targetObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
#if (UNITY_ANDROID || UNITY_IOS || UNITY_WP8 || UNITY_WP8_1) && !UNITY_EDITOR
//Handle mobile touch input
for (var i = 0; i < Input.touchCount; ++i)
{
Touch touch = Input.GetTouch(i);
if (touch.phase == TouchPhase.Began)
{
MoveToTarget(touch.position);
}
}
#else
//Handle mouse input
if (Input.GetKeyDown(KeyCode.Mouse0))
{
MoveToTarget(Input.mousePosition);
}
#endif
//Camera follow
playerCamera.transform.position = Vector3.Lerp(playerCamera.transform.position, transform.position + cameraOffset, Time.deltaTime * 7.4f);
playerCamera.transform.LookAt(transform);
}
void MoveToTarget(Vector2 posOnScreen)
{
//print("Move To: " + new Vector2(posOnScreen.x, Screen.height - posOnScreen.y));
Ray screenRay = playerCamera.ScreenPointToRay(posOnScreen);
RaycastHit hit;
if (Physics.Raycast(screenRay, out hit, 75))
{
agent.destination = hit.point;
//Show marker where we clicked
if (targetObject)
{
targetObject.transform.position = agent.destination;
targetObject.SetActive(true);
}
}
}
}
第2步
现在让我们设置玩家控制器和游戏关卡。
- 创建一个新的 GameObject 并调用它 'RTSPlayer'
- 将 RTSPlayerController.cs 脚本附加到它(注意:附加后,它将自动添加另一个名为 NavMeshAgent 的组件,稍后将需要该组件)
- 添加一个玩家主体(在我的例子中,我将使用一个带有 cube 的简单胶囊,但如果有的话,您可以添加一个玩家模型)。将其缩小直到所需的大小。
- 将玩家模型移动到 'RTSPlayer' 游戏对象内(注意:在建立父级之前,请确保 'RTSPlayer' 放置在玩家模型的底部)
- 选择 'RTSPlayer' 并在 NavMeshAgent 中调整半径和高度,直到它与玩家模型匹配
- 接下来是创建一个目标指示器 prefab。这只是一个带有四边形的简单游戏对象,它将指示我们在地图上单击的位置。
您可以使用下面的纹理:
- 最后,选择 'RTSPlayer' 并在 RTSPlayerController 脚本中分配所有必要的变量:
玩家相机 - 不言自明,这可以是任何相机
相机偏移 - 相机距离玩家的距离
Target Indicator Prefab - 我们刚刚创建的预制件
在“游戏”模式下,您会注意到单击地图不会使玩家移动。那是因为我们还有最后一件事要做,那就是烘焙 Navigation Mesh (Navmesh):
- 选择属于地图一部分的所有对象并将它们标记为静态:
- 转到窗口 -> AI -> 导航
- 在“烘焙”选项卡下,更改“代理半径”和“代理高度”的值(这些值应与 NavMeshAgent 中的值匹配),然后单击“烘焙”。
- 烘焙完成后,您会注意到一个蓝色轮廓的网格,它代表可步行区域。
注意:为了防止玩家翻山越岭,请返回“烘焙”选项卡并减小“最大坡度”角度,然后重新烘焙导航网格。
好多了!
最后,返回“播放”模式并左键单击地图上的某个位置。
玩家现在应该向目标移动,同时避开障碍物:
提示:调整 NavMeshagent 的速度、角速度和加速度值以满足您的需求。