So lately I’ve been making a script that controls a space plane. It is for mobile, so it doesn’t have to be 100% realistic. I have a joystick that determines direction and a slider that determines speed.
First, I went with something like Rigidbody.AddForce(transform.forward * Time.deltaTime*speed). This worked, but made for very slow gameplay because most of the time when playing I’d have to try to counter old forces. While probably the most realistic for a space plane, it makes for some horrible gameplay.
Second, I went to Transform.Translate(transform.forward * Time.deltaTime*speed). This worked pretty well, while pretty unrealistic it was much better than my older method. However if I crash into objects at high speed, the plane will go right thru them. While in-game I’d probably destroy the plane, this could lead to some considerable bugs. After considerable tweaking I could probably get it to work.
So today I wanted to make the plane flip and accidentally ran into Rigidbody.AddForce(speed, 0, 0, ForceMode.Impulse). This looked pretty interesting. After more testing, I noticed that Rigidbody.AddForce also works better with collisions. So now I’m interested in re-writing my script to use the 3rd method.
Before I invest a lot of time into that, what is your opinion? If you were in my spot, would you use the 3rd method, or would you try something else?
This is way of using AddForce is incorrect. You shouldn’t use deltaTime here. Also, speed is incorrect because you’re aplying a force (N, newtons), not a speed (m/s, meters per second).
I’m not sure on what are you trying to do exactly, but this would be more correct when used within FixedUpdate:
Currently this is the state of my script. Feeling proud but something tells me I’m doing this badly lol
Feel free to take a look if interested. Perhaps it might be useful for your projects
using UnityEngine;
using System.Collections;
public class TransformController : MonoBehaviour {
//using default joystick
public UnityStandardAssets.CrossPlatformInput.Joystick joystick;
//joystick positions
public float Joyx = 0, Joyy = 0;
//original position of joystick
public Vector3 OrigPos;
//current position of joystick
public Vector3 CurrPos;
//difference--how much the joystick has moved compared to original position
public float DiffX;
public float DiffY;
//ratio of current difference and max possible difference
//used to calculate how fast to move the plane based on how much the joystick is moved
public float DiffXRatio;
public float DiffYRatio;
//how much the joystick moves from the center
public float MovementRange;
//max speed the plane moves forward
public float MaxForwardSpeed;
//max speed the plane moves sideways
public float MaxHorizontalSpeed;
//slider that decides forward speed
public SpeedSlider SpeedSlider;
//will decide how to control plane once on land LATER
public bool LandingStatus;
private Rigidbody Rigid;
// Use this for initialization
void Start ()
{
//set original joystick position
OrigPos = joystick.transform.position;
Rigid = this.gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate ()
{
Joyx = joystick.transform.position.x;
Joyy = joystick.transform.position.y;
//find the diffirence of joystick position
DiffX = Joyx - OrigPos.x;
DiffY = Joyy - OrigPos.y;
//now find the ratio
DiffXRatio = DiffX / joystick.MovementRange;
DiffYRatio = DiffY / joystick.MovementRange;
CurrPos = joystick.transform.position;
//now that we have calculated the joystick's positions, let's move the plane
//first, we need to make sure we're not landing!
if (LandingStatus == false)
{
//BETA CODE---- Don't waste time on this atm
//want to put in flips
//for now just X
//if (DiffXRatio >= 0.7)
//{
// //flip plane
// FlipPlaneXPlus();
//}
//if (DiffXRatio <= -0.7)
//{
// //flip plane
// FlipPlaneXMinus();
//}
//apply controls
ControlPlane2();
//move plane forward
Rigid.MovePosition(transform.position + transform.forward * Time.deltaTime * SpeedSlider.SpeedSliderValue * MaxForwardSpeed);
}
}
//why is this all commented? This is old code that shouldn't be used
//this uses Transform.Translate. Migrating to AddForce
//http://forum.unity3d.com/threads/which-of-these-methods-is-the-best-for-moving-a-spaceplane.425901/#post-2752770
//void ControlPlane()
//{
// Rigid.velocity = Vector3.zero;
// Rigid.angularVelocity = Vector3.zero;
// //how much to move the plane
// float XMovement = DiffXRatio * MovementRange;
// float YMovement = DiffYRatio * MovementRange;
// //I do NOT know why this is inversed... but so be it!
// //rotate up-down
// transform.Rotate(Vector3.right * Time.deltaTime * YMovement);
// //rotate right-left
// transform.Rotate(Vector3.up * Time.deltaTime * XMovement);
// //tilt as rotating
// transform.Rotate(Vector3.back * Time.deltaTime * XMovement * TiltFactor);
// //now that all the rotating is done, we need to move the plane
// //TESTING Space.World... never used this
// transform.Translate(Vector3.right * Time.deltaTime * XMovement * MaxHorizontalSpeed, Space.World);
//}
//currently using this to control plane
void ControlPlane2()
{
//how much to move the plane
float XMovement = DiffXRatio * MovementRange;
float YMovement = DiffYRatio * MovementRange;
//I do NOT know why this is inversed... but so be it!
//rotate up-down
transform.Rotate(Vector3.right * Time.deltaTime * YMovement);
//rotate right-left
transform.Rotate(Vector3.up * Time.deltaTime * XMovement);
//tilt as rotating
transform.Rotate(Vector3.back * Time.deltaTime * XMovement);
//now that all the rotating is done, we need to move the plane
Rigid.MovePosition(transform.position + transform.right * XMovement * MaxHorizontalSpeed * Time.deltaTime);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "StopPosition")
{
//Cool tip!
//For some reason, I need to "penetrate" (no, not in THAT way ;) the collider before stopping the player
//so I'll wait a bit before stopping the player
StartCoroutine(Penetrate());
Debug.Log("Player Stopped");
}
}
IEnumerator Penetrate()
{
yield return new WaitForSeconds(0.6f);
LandingStatus = true;
}
//CURRENTLY don't need this
//void FlipPlaneXPlus()
//{
// transform.Rotate(Vector3.back * Time.deltaTime * 300);
// Rigid.AddForce(1000, 0, 0, ForceMode.Impulse);
//}
void FlipPlaneXMinus()
{
}
}
Thanks. Not sure what I gained by using Rigidbody.MovePosition and Rigidbody.MoveRotation instead of transform.translate and transform.rotate, but at least I’m doing things properly for once
Here’s the updated void ControlPlane2:
void ControlPlane2()
{
//how much to move the plane
float XMovement = DiffXRatio * MovementRange;
float YMovement = DiffYRatio * MovementRange;
//I do NOT know why this is inversed... but so be it!
//rotate up-down
Rigid.MoveRotation(Rigid.rotation * Quaternion.Euler(Vector3.right * Time.deltaTime * YMovement));
//rotate right-left
Rigid.MoveRotation(Rigid.rotation * Quaternion.Euler(Vector3.up * Time.deltaTime * XMovement));
//tilt as rotating
Rigid.MoveRotation(Rigid.rotation * Quaternion.Euler(Vector3.back * Time.deltaTime * XMovement));
//now that all the rotating is done, we need to move the plane
Rigid.MovePosition(transform.position + transform.right * XMovement * MaxHorizontalSpeed * Time.deltaTime);
}
You may use deltaTime anywhere. deltaTime always contains the proper value based on the method it’s being used from. When used from FixedUpdate, deltaTime = fixedDeltaTime. When used from Update, deltaTime = last visual frame’s time.