您的位置:首页 > 移动开发 > Unity3D

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:

// 用户球控制器
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中了。

 

好了,我再去看下一个脚本
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: