博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
unity2D 船只型物体驱动的实现
阅读量:7044 次
发布时间:2019-06-28

本文共 3660 字,大约阅读时间需要 12 分钟。

  • 船只向前行驶的驱动力

假设在水中没有摩擦阻力,船只有惯性,船只可以转弯,按下前进键时船只会在力的作用下使得自身的物理运动方向变化到自身的前方方向,从而向前行进。

上图中

V:船当前物理速度

V1,V2:V在两个方向上的分速度

 Vn:船要达到的目标速度

假设

船的最大前进推进力为pushForce,船的最大速率只能是maxSpeed。

具体思想为:将V分解为V1和V2,利用V1,V2和Vn的关系,得出当前的船需要添加的恒力,下面总结出三种方案。

 

第一种:

制动力和推进力分离

1.先得出在船正方向的最大力Fn,这里可以抽象的认为这个力是一直添加在船的正方向的,就像火箭的推进引擎。

2.制动力,这是另外计算的,根据当前的船的速度,以及Fn,得出,然后和已经添加的Fn相加得出当前需要添加到恒力组件上的力(由于概念问题,这里Fn做了一次不必要的计算)

第二种:

驱动力即是制动力,也就是一次性计算

用最大正方向速度向量减去当前速度向量,得到和船的偏移向量刚好相反但是模相等的抵消向量。为了抵消偏移向量,让pushForce乘以   该抵消向量的单位向量,从而得到需要添加到恒力组件上的力

改良:为了防止抖动,求出需要的力向量后,让当前组件上的力渐变到求出的力。

第三种:

将当前速度方向分解为V1和V2,然后计算两个垂直方向上需要添加的力,最后又这两个力相加得到需要的力向量

 

可以看出,其实上面三种方案最后的结果都是相同的,只是为了功能上的需求,以及防止物理演算失真的原因,从而得到的三种不同的计算方案

 

方案2的unity代码如下

using System.Collections;using System.Collections.Generic;using UnityEngine;public class Player01Test : MonoBehaviour{    public float rotateSpeed;//旋转速度    ConstantForce2D constantForce2D;//恒力组件    public float maxSpeed;//最大速度    Rigidbody2D rigid2D;    //推力参数    public float pushForce;//推力大小    //[HideInInspector]    //public float currentForce;//当前推力    // Start is called before the first frame update    void Start()    {        constantForce2D = GetComponent
(); rigid2D = GetComponent
(); } private void FixedUpdate() { //旋转 //为利用扭矩力使得船往某个方向旋转 if (Input.GetKey(KeyCode.LeftArrow))//按下左方向键,船往顺时针旋转 { //transform.Rotate(new Vector3(0, 0, rotateSpeed * Time.fixedDeltaTime)); if (rigid2D.angularVelocity >= 200)//如果旋转速度已经达到最大,那么撤销扭矩力 constantForce2D.torque = 0; else //否则添加扭矩力 constantForce2D.torque = 600; rigid2D.angularDrag = 0; } else if (Input.GetKey(KeyCode.RightArrow))//按下右方向键,船往逆时针旋转 { //transform.Rotate(new Vector3(0, 0, -rotateSpeed * Time.fixedDeltaTime)); if (rigid2D.angularVelocity <= -200) constantForce2D.torque = 0; else constantForce2D.torque = -600; rigid2D.angularDrag = 0; } else { constantForce2D.torque = 0; rigid2D.angularDrag = 50; } //推进 if (Input.GetKey(KeyCode.UpArrow)) { Vector3 Vn= transform.up * maxSpeed;//船需要达到的目标速度 Vector3 V = rigid2D.velocity;//当前的速度(方向不一定是当前的船正方向) Vector3 forceDir = (Vn - V).normalized;//获得力方向的单元向量 //添加力到船的恒力组件上 constantForce2D.force = forceDir * pushForce; /*//这里为改进代码方式0,用来代替上面这段代码,即允许微小误差存在,主要是防止物理演算的失真抖动 if (forceDir.magnitude>Time.fixedDeltaTime*pushForce) constantForce2D.force = forceDir * pushForce; else constantForce2D.force = Vector3.zero; */ } else//如果没有添加任何力,那么让恒力组件为0 { constantForce2D.force = Vector3.zero; } }}

组件

 

 

  • 船只转弯的驱动

为了方便理解这里进行类似例子引申:

以2d为例,一个小球在一个横杆上,小球唯一的移动方式是设置constant force组件的方向力,小球有惯性,没有摩擦力,如何让小球移动到杆上的任意一个点,并且在该点的速度刚好为0?

很显然,在物理上这个问题很难解决,因此解决的方案是如何让小球无限的接近目标点,并且速度为0。

 

问题的关键:

如何在力的 作用下到达目标点

如何在力的作用下变化到目标速度

(这里就可想象为到达目标点时,速度为0)

 

方案一:(太复杂,以后考虑)

设置减速半径,当运动到里目标点距离为减速半径的长度时进行减速操作。减速力为,减速力为偏移距离剧偏移半径的百分比乘以最大推力,方向为速度的反方向。偏移半径为,最大速度在最大力的反作用下减速到0,期间运动的距离刚好为减速半径(改进,在变力的情况下速度减到0,运动的距离为偏移半径)

 

方案二:(太简单太low)

进入减速半径后直接使用rigidbody上的迟滞力,将迟滞力放到最大

 

方案三:(明确简单,优先选择)

1.如果大于减速距离,那么用力驱使速度朝向目标方向移动,目标速度为最大速度

2.如果小于减速距离,那么用力驱使速度朝向目标方向,目标速度为迟滞速度(迟滞速度比最大速度小得多,便于操作调节运动的位置)

3.如果小于迟滞距离:如果当前速度大于迟滞速度,那么设置目标速度为0,此时如果速度小于迟滞速度,那么设置线性阻尼为最大(改进:如果速度方向与目标方向相反,把目标速度改为朝向目标点的迟滞速度);如果速度小于迟滞速度,那么设置线性阻尼为最大(改进:如果速度方向与目标方向相反,把目标速度改为朝向目标点的迟滞速度)。

从而使得角色最大程度的靠近目标点,并且速度为0.

 

转载于:https://www.cnblogs.com/xiaoahui/p/10479694.html

你可能感兴趣的文章
阿里顶级Java架构师,教你这样手写Spring!
查看>>
android课程表控件、悬浮窗、Todo应用、MVP框架、Kotlin完整项目源码
查看>>
CLOB字段在java中操作
查看>>
磁盘清理
查看>>
javascript 判断数据类型 判空
查看>>
matplotlib 中文字体问题
查看>>
protobuf v3测试
查看>>
(1)知识准备【利用objective-c的runtime特性,结合FMDB实现一个轻量级的ORM】
查看>>
Angular js开发的各种坑(持续更新中。。。)
查看>>
Google Apps - Gmail API的通知功能
查看>>
调试java8 函数式
查看>>
Intellij使用心得(二) -- 关于启动Web服务器的几个事
查看>>
linux源代码安装软件
查看>>
2013年4月IT技术行业网站综合影响力排名
查看>>
Magento session机制的分析与应用
查看>>
linux 服务器长ping 加时间戳;转
查看>>
http与https的区别
查看>>
一些可以查询IP地理位置、身份证所在地、手机归属地的接口
查看>>
鼠标滚动插件smoovejs和wowjs
查看>>
我的友情链接
查看>>