Unity基础包 刚体球类 Ball和BallUserControl 脚本研究
2016-11-17 11:01
316 查看
版本:unity 5.3.4 语言:C#
今天是两个球体脚本的分析,利用刚体作用力直接产生移动的方式进行移动,让我想起很早的一个游戏——仓鼠球。
我感觉在这类的控制方面,有了刚体之后真的是简便了很多,一个球体放在地上,给与一个力自然就会旋转,不然旋转什么的自己写还是有点麻烦的吧。
首先是Ball类,主要提供了移动的方法:
// 球型物体移动类,由刚体实现,注意这边的角阻力设置为了1,设为0话会一直转,停不下来
public class Ball : MonoBehaviour
{
[SerializeField] private float m_MovePower = 5; //驱动球移动的力量值
[SerializeField] private bool m_UseTorque = true; //驱动球的时候是否使用扭转力,即旋转力
[SerializeField] private float m_MaxAngularVelocity = 25; //球最大能旋转的速度
[SerializeField] private float m_JumpPower = 2; //球跳跃时所产生的力
private const float k_GroundRayLength = 1f; //射线确认球是否在地上的长度
private Rigidbody m_Rigidbody; //球的刚体
// 初始化
private void Start()
{
m_Rigidbody = GetComponent<Rigidbody>();
// 设置最大的角速度,默认是7
GetComponent<Rigidbody>().maxAngularVelocity = m_MaxAngularVelocity;
}
// 移动,由具体的控制器调用
public void Move(Vector3 moveDirection, bool jump)
{
if (m_UseTorque)
{
// 如果是否旋转力,则在轴线方向添加力,即要向x轴前进,顺时针旋转z轴;向z轴前进,逆时针旋转x轴,最后乘以力的值
m_Rigidbody.AddTorque(new Vector3(moveDirection.z, 0, -moveDirection.x)*m_MovePower);
}
else
{
// 线性力的话就直接加就行
m_Rigidbody.AddForce(moveDirection*m_MovePower);
}
//如果在地上而且弹跳键被按下,则网上添加一个冲力。这边用了一条射线往下发射,判断是否在地上,就不能用Vector3.down吗,非要用Vector3.up,我愣了三秒为什么要往上发射
if (Physics.Raycast(transform.position, -Vector3.up, k_GroundRayLength) && jump)
{
m_Rigidbody.AddForce(Vector3.up*m_JumpPower, ForceMode.Impulse);
}
}
}
这边就是有两种方式,一种是以旋转力作为移动,而另一种是直接给一个线性力,两种感觉都可以,不过仓鼠球的话旋转力是最真实的吧。
接下来是用户控制类BallUserControl:
读入用户的输入,然后计算出对应的方向,最后在FixedUpdate中控制ball移动。这个流程是比较规范的一个写法吧,像我之前一些更新代码都卸载Update中了。
好了,我再去看下一个脚本
今天是两个球体脚本的分析,利用刚体作用力直接产生移动的方式进行移动,让我想起很早的一个游戏——仓鼠球。
我感觉在这类的控制方面,有了刚体之后真的是简便了很多,一个球体放在地上,给与一个力自然就会旋转,不然旋转什么的自己写还是有点麻烦的吧。
首先是Ball类,主要提供了移动的方法:
// 球型物体移动类,由刚体实现,注意这边的角阻力设置为了1,设为0话会一直转,停不下来
public class Ball : MonoBehaviour
{
[SerializeField] private float m_MovePower = 5; //驱动球移动的力量值
[SerializeField] private bool m_UseTorque = true; //驱动球的时候是否使用扭转力,即旋转力
[SerializeField] private float m_MaxAngularVelocity = 25; //球最大能旋转的速度
[SerializeField] private float m_JumpPower = 2; //球跳跃时所产生的力
private const float k_GroundRayLength = 1f; //射线确认球是否在地上的长度
private Rigidbody m_Rigidbody; //球的刚体
// 初始化
private void Start()
{
m_Rigidbody = GetComponent<Rigidbody>();
// 设置最大的角速度,默认是7
GetComponent<Rigidbody>().maxAngularVelocity = m_MaxAngularVelocity;
}
// 移动,由具体的控制器调用
public void Move(Vector3 moveDirection, bool jump)
{
if (m_UseTorque)
{
// 如果是否旋转力,则在轴线方向添加力,即要向x轴前进,顺时针旋转z轴;向z轴前进,逆时针旋转x轴,最后乘以力的值
m_Rigidbody.AddTorque(new Vector3(moveDirection.z, 0, -moveDirection.x)*m_MovePower);
}
else
{
// 线性力的话就直接加就行
m_Rigidbody.AddForce(moveDirection*m_MovePower);
}
//如果在地上而且弹跳键被按下,则网上添加一个冲力。这边用了一条射线往下发射,判断是否在地上,就不能用Vector3.down吗,非要用Vector3.up,我愣了三秒为什么要往上发射
if (Physics.Raycast(transform.position, -Vector3.up, k_GroundRayLength) && jump)
{
m_Rigidbody.AddForce(Vector3.up*m_JumpPower, ForceMode.Impulse);
}
}
}
这边就是有两种方式,一种是以旋转力作为移动,而另一种是直接给一个线性力,两种感觉都可以,不过仓鼠球的话旋转力是最真实的吧。
接下来是用户控制类BallUserControl:
// 用户球控制器 public class BallUserControl : MonoBehaviour { private Ball ball; //球移动类的引用 private Vector3 move; //世界坐标中的移动方向,使用相机的前方和用户输入来计算 private Transform cam; //主相机 private Vector3 camForward; //主相机当前的前方 private bool jump; //当前的跳跃键是否被按下 private void Awake() { // 设置引用 ball = GetComponent<Ball>(); //获取主相机 if (Camera.main != null) { cam = Camera.main.transform; } else { //在这个例子中我们使用世界坐标来控制,也许这不是他们做希望的,不过我们至少警告一下他们 Debug.LogWarning("警告:不存在一个主相机,球需要一个tag为MainCamera的相机,来做相机关联的移动"); } } private void Update() { //获取轴线和跳跃的输入 float h = CrossPlatformInputManager.GetAxis("Horizontal"); float v = CrossPlatformInputManager.GetAxis("Vertical"); jump = CrossPlatformInputManager.GetButton("Jump"); //计算移动方向 if (cam != null) { //计算世界坐标的相机相关的方向 camForward = Vector3.Scale(cam.forward, new Vector3(1, 0, 1)).normalized; //获取相机的正方向,忽略y坐标,不过cam.right为什么不忽略? move = (v * camForward + h * cam.right).normalized; //move = (v*cam.forward + h*cam.right).normalized; //使用这个,当然也能移动,不过官方写的更加强调正方向,水平方向有输入的情况下,官方的转弯幅度更小 } else { //当没有相机时,直接以世界坐标轴作为参考 move = (v*Vector3.forward + h*Vector3.right).normalized; } } private void FixedUpdate() { //使用move方法控制球 ball.Move(move, jump); jump = false; } }
读入用户的输入,然后计算出对应的方向,最后在FixedUpdate中控制ball移动。这个流程是比较规范的一个写法吧,像我之前一些更新代码都卸载Update中了。
好了,我再去看下一个脚本
相关文章推荐
- Unity基础包 刚体TPS类 3个第三人称脚本的研究
- Unity基础包 刚体FPS HeadBob和CameraRefocus 脚本研究
- Unity基础包 刚体FPS RigidbodyFirstPersonController 脚本研究
- Unity基础包 FirstPersonController下的FOVKick 脚本研究
- Unity学习笔记——Unity基础四:刚体及脚本初步
- Unity基础包 FirstPersonController下的MouseLook 脚本研究
- Unity基础包 FirstPersonController下的CurveControlledBob和LerpContolledBob 脚本研究
- Unity基础包 FirstPersonController下的MouseLook 脚本研究
- Unity基础包 FirstPersonController 脚本研究
- 【Unity3D基础教程】给初学者看的Unity教程(二):所有脚本组件的基类 -- MonoBehaviour的前世今生
- 【Unity3D基础教程】给初学者看的Unity教程(二):所有脚本组件的基类 -- MonoBehaviour的前世今生
- 【蓝鸥Unity开发基础三】课时14 刚体
- 【蓝鸥Unity开发基础三】课时6 脚本生命周期
- 【Unity基础知识②】创建C#脚本、Debug.log输出语句
- Unity基础|Unity脚本创建与执行
- Unity脚本基础
- [Unity基础]unity脚本的生命周期
- Unity学习之基础脚本代码抽象类和继承总结
- 【蓝鸥Unity开发基础三】课时15 刚体和Collider
- Gradle-user guide-第6章 构建脚本基础(译) --续