How can i display the acceleration value of my spaceship? - c#

While the game is running and i press none stop on the key p i see the spaceship moving faster and faster. But the value of the variable thrust is all the 5 never change. Then what value show and change that make the acceleration ? And what the thrust do ? If i change the thrust from 5 to 10 ?
I added to my spaceship a Rigidbody component.
The way i'm doing it is the right way to add acceleration to my spaceship ?
I want to display in the OnGUI the value of the acceleration each time i press the p key.
using UnityEngine;
using System.Collections;
public class ControlShip : MonoBehaviour {
public int rotationSpeed = 75;
public int movementspeed = 10;
private int thrust = 5;
Rigidbody _rigidbody;
void Start () {
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
void Update () {
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey("p"))
{
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
}
void OnGUI()
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + thrust);
}
}
Update
My script now after changes. When i press the p key the spaceship is gone fast and the value of the acceleration is 0 all the time in the OnGUI:
using UnityEngine;
using System.Collections;
public class ControlShip : MonoBehaviour {
public int rotationSpeed = 75;
public int movementspeed = 10;
private int thrust = 5;
bool isPKeyDown = false;
float acceleration = .0f;
Vector3 previousPosition = Vector3.zero;
Rigidbody _rigidbody;
// Use this for initialization
void Start () {
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update () {
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey("p"))
{
isPKeyDown = Input.GetKey("p");
float distance = Vector3.Distance(previousPosition, transform.position);
float acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, acceleration, ForceMode.Acceleration);
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}

Starting from the beginnig, thrust is the value of the actual force ( a push force ) for your starship. So the bigger the value the stronger it "pushes" your starship.
If your script works then yes it is a good way of adding acceleration ( that depends on what you think )
To be able to show acceleration value when user pushes "P" key you should calculate the acceleration value ( how to calculate, or just use #Dan Wilson answer/comment ).
Then you should modify your Update method:
public void Update(){
isPKeyDown = Input.GetKey("p");
// ... rest of your code
}
update your class members:
bool isPKeyDown = false;
float acceleration = .0f;
update your OnGUI method:
public void OnGUI(){
if ( isPKeyDown ) {
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
and to calculate your acceleration and playing with rigidbody i would recommend using fixed update:
public void FixedUpdate(){
// calculate acceleration here...
acceleration = ... ;
if ( isPKeyDown ) {
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
}
EDIT:
Easiest way of finding out the acceleration:
// as a member field
Vector3 previousPosition = Vector3.Zero;
// in update
float distance = Vector3.Distance(previousPosition, transform.Position);
float acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.Position;
EDIT2:
updated code on pastebin

I think what you're looking for is velocity. And to see the acceleration over a specific time interval you need to compare the difference in velocity divided by the time between them. The value 5 you're printing is the value you add, not the value of the spaceship.
acceleration = (rigidbody.velocity - lastVelocity) / Time.fixedDeltaTime;
lastVelocity = rigidbody.velocity;
Further reading with this example here

Related

Why do objects stutter while I move and the camera is rotating?

I have began developing an fps script and followed a tutorial to help with the script. Everything works great now but the only issue is any objects in the view seem to stutter whenever the player is moving and rotating at the same time.
The script for the player's movement and camera rotation is below.
Can anybody point me in the right direction?
Thank you.
{
public Transform cam;
public Rigidbody rb;
public float camRotationSpeed = 5f;
public float camMinimumY = -60f;
public float camMaximumY = 75f;
public float rotationSmoothSpeed = 10f;
public float walkSpeed = 9f;
public float runSpeed = 14f;
public float maxSpeed = 20f;
public float jumpPower = 30f;
public float extraGravity = 45;
float bodyRotationX;
float camRotationY;
Vector3 directionIntentX;
Vector3 directionIntentY;
float speed;
public bool grounded;
void Update()
{
LookRotation();
Movement();
ExtraGravity();
GroundCheck();
if(grounded && Input.GetButtonDown("Jump"))
{
Jump();
}
}
void LookRotation()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
bodyRotationX += Input.GetAxis("Mouse X") * camRotationSpeed;
camRotationY += Input.GetAxis("Mouse Y") * camRotationSpeed;
camRotationY = Mathf.Clamp(camRotationY, camMinimumY, camMaximumY);
Quaternion camTargetRotation = Quaternion.Euler(-camRotationY, 0, 0);
Quaternion bodyTargetRotation = Quaternion.Euler(0, bodyRotationX, 0);
transform.rotation = Quaternion.Lerp(transform.rotation, bodyTargetRotation, Time.deltaTime * rotationSmoothSpeed);
cam.localRotation = Quaternion.Lerp(cam.localRotation, camTargetRotation, Time.deltaTime * rotationSmoothSpeed);
}
void Movement()
{
directionIntentX = cam.right;
directionIntentX.y = 0;
directionIntentX.Normalize();
directionIntentY = cam.forward;
directionIntentY.y = 0;
directionIntentY.Normalize();
rb.velocity = directionIntentY * Input.GetAxis("Vertical") * speed + directionIntentX * Input.GetAxis("Horizontal") * speed + Vector3.up * rb.velocity.y;
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
if (Input.GetKey(KeyCode.LeftShift))
{
speed = runSpeed;
}
if (!Input.GetKey(KeyCode.LeftShift))
{
speed = walkSpeed;
}
}
void ExtraGravity()
{
rb.AddForce(Vector3.down * extraGravity);
}
void GroundCheck()
{
RaycastHit groundHit;
grounded = Physics.Raycast(transform.position, -transform.up, out groundHit, 1.25f);
}
void Jump()
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
This probably happens because the frame needs to update the camera rotation and the player position at the same time. i would suggest doing the rotation of the camera in fixed update. because this will run at the end of each frame.
like this:
void FixedUpdate()
{
LookRotation();
}
another thing i would suggest is to move the player while the groundcheck is being ran, because if you do it seperately i can see a bug coming up when the player moves faster then the code can run or something. so a tip would be or to run it inside the movement method, or call the method while you are calling the movement method.
this:
void Movement()
{
directionIntentX = cam.right;
directionIntentX.y = 0;
directionIntentX.Normalize();
directionIntentY = cam.forward;
directionIntentY.y = 0;
directionIntentY.Normalize();
rb.velocity = directionIntentY * Input.GetAxis("Vertical") * speed + directionIntentX * Input.GetAxis("Horizontal") * speed + Vector3.up * rb.velocity.y;
rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxSpeed);
if (Input.GetKey(KeyCode.LeftShift))
{
speed = runSpeed;
}
if (!Input.GetKey(KeyCode.LeftShift))
{
speed = walkSpeed;
}
GroundCheck();
}
or litteraly copy and paste the code within your movement method.

How to create a 'sprint' ability in a 2d game

I'm trying to create an ability of sprinting in 2d Unity (C#) that has an energy bar so it can't be used endlessly. What am I missing?
I've tried making sprint a function and call it when the X key was pressed. Tried to multiply the position of it but I got a blinking ability over a short distance.
\\ this is my movement script, other variables we're declared earlier in the code
void Update() {
Vector2 mi = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
mv = mi.normalized * speed;
}
private void FixedUpdate() {
rb.MovePosition(rb.position + mv * Time.fixedDeltaTime);
}
I expect the code to make the player go twice the normal speed when the X key is pressed but it can only be used when the energy hasn't ran out.
Don't see your implementation of "energy" but I would simply use a
public float energy;
// How much is energy reduced per second?
public float decreaseSpeed;
for increasing the speed if x is pressed do
private void Update()
{
Vector2 mi = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
mv = mi.normalized * speed;
if(Input.GetKey(KeyCode.X) && energy > 0)
{
// Reduce energy by decreaseSpeed per second
energy -= decreaseSpeed * Time.deltaTime;
// if needed avoid negative value
energy = Mathf.Max(0, energy);
// double the move distance
mv *= 2;
}
}
Btw ot is recommended to use Time.deltaTime instead of Time.fixedDeltaTime also in FixedUpdate (see Time.fixedDeltaTime)
In Update check if sprint axis (create a Sprint axis in the project input settings). Also, have a variable for how fast your energy bar drains while sprinting:
public float energyBarDrainRate = 1f;
private bool isSprinting = false;
void Update() {
isSprinting = Input.GetAxis("Sprint") > 0f;
Vector2 mi = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
mv = mi.normalized * speed;
}
Then in fixedupdate, check if your energy bar has enough to drain for that frame, and if it does then drain it and increase the effective movespeed that frame:
private void FixedUpdate() {
float energyToDrain = energyBarDrainRate * Time.deltaTime
bool drainSprint = energyAmount > energyToDrain ;
float effectiveMv = mv;
if (drainSprint && isSprinting) {
effectiveMv = mv * 2f;
energyAmount -= energyToDrain;
}
rb.MovePosition(rb.position + effectiveMv * Time.deltaTime);
}

How can i make the spaceship to land automatic on the base?

The base is a red cube.
The spaceship is moving already when the game start.
When I click/press the L button the spaceship rotates to face the base and starts moving to it but then when it's getting close to the base it's behaving unexpectedly and the spaceship starts rolling around the base nonstop.
What I want is to make the landing automatic like this youtube video of blender.
I don't want the graphics but the way it's landing.
Blender landing spaceship
And this is a short video clip showing my spaceship when it's start landing:
Landing test
This is the script i'm using for controlling the spaceship and the landing part should be automatic.
The script is attached to the spaceship.
using UnityEngine;
using System.Collections;
public class ControlShip : MonoBehaviour {
public int rotationSpeed = 75;
public int movementspeed = 10;
public int thrust = 10;
public float RotationSpeed = 5;
private bool isPKeyDown = false;
private float acceleration = .0f;
private Vector3 previousPosition = Vector3.zero;
private Rigidbody _rigidbody;
private bool landing = false;
private Vector3 originPosition;
private Vector3 lastPosition;
private const float minDistance = 0.2f;
private Transform baseTarget;
// Use this for initialization
void Start () {
baseTarget = GameObject.Find("Base").transform;
originPosition = transform.position;
_rigidbody = GetComponent<Rigidbody>();
Debug.Log("Acc Speed: " + thrust);
}
// Update is called once per frame
void Update()
{
if (landing == false)
{
var v3 = new Vector3(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
transform.Rotate(v3 * rotationSpeed * Time.deltaTime);
transform.position += transform.forward * Time.deltaTime * movementspeed;
if (Input.GetKey(KeyCode.Z))
transform.Rotate(Vector3.forward * rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.R))
transform.Rotate(Vector3.right * rotationSpeed * Time.deltaTime);
if (Input.GetKey(KeyCode.P))
{
isPKeyDown = Input.GetKey(KeyCode.P);
float distance = Vector3.Distance(previousPosition, transform.position);
acceleration = distance / Mathf.Pow(Time.deltaTime, 2);
previousPosition = transform.position;
_rigidbody.AddRelativeForce(0f, 0f, thrust, ForceMode.Acceleration);
}
}
else
{
transform.position += transform.forward * Time.deltaTime * movementspeed;
var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
var str = Mathf.Min(.5f * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
}
if (landed == true)
TakeOff();
if (Input.GetKey(KeyCode.L))
{
landing = true;
lastPosition = transform.position;
}
}
void OnTriggerEnter(Collider other)
{
if (landing == true && other.gameObject.name == "Base")
{
StartCoroutine(Landed());
}
}
bool landed = false;
IEnumerator Landed()
{
yield return new WaitForSeconds(5);
Debug.Log("Landed");
landed = true;
}
private void TakeOff()
{
if (transform.position != originPosition)
{
_rigidbody.AddForce(transform.up * 10);
}
if ((transform.position - originPosition).sqrMagnitude <= (1f * 1f))
{
landed = false;
_rigidbody.useGravity = false;
}
}
void OnGUI()
{
if (isPKeyDown)
{
GUI.Label(new Rect(100, 100, 200, 200), "Acc Speed: " + acceleration);
}
}
}
This is the part of the landing, should be the part of the landing:
transform.position += transform.forward * Time.deltaTime * movementspeed;
var targetRotation = Quaternion.LookRotation(baseTarget.position - transform.position);
var str = Mathf.Min(.5f * Time.deltaTime, 1);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, str);
The spaceship have two components: Rigidbody, Use Gravity set to true. And a Box Collider.
The Base have a box collider component.
You appear to have a box collider on your vehicle and it looks as though it is colliding with the terrain when your code tries to bring it in for a landing. Try switching the collider to be a trigger(tick option on collider component).
Then try it again, as this will not cause physical collisions. If it works or fails for a totally different reason you know this is the cause or a contributing factor.
EDIT: It is worth also noting that when trying to achieve this kind of effect it can be much easier to trigger an animation than try to achieve it in physics based code. Unity offers some great animation controllers and you can call an animation when you need to land since you are taking control away from the player anyway.
While doing this you could turn off the collider so you don't get any strange collision then turn it on when the ship needs to take off, provided you need that of course.
Hope it helps.

2D Flight simulator physics in Unity

I'm tring to implement a simple (but realistic as possible) 2D flight simulator in Unity using its 2D engine.
I have taken some sources around and tried to compile my own (without success) ... i must admit i'm a math and c# newbie; forgive my ignorance ..
Ideally i would like to achieve something like this :
http://runway.countlessprojects.com/prototype/index.html
Any ideas / corrections / suggestions welcome
using UnityEngine;
using System.Collections;
public class FlightControl : MonoBehaviour {
public float energy;
public float roll;
public float tilt;
public float yaw;
public float airspeed;
public float fall;
public float tip;
Rigidbody2D rb;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
void Start () {
}
void Update () {
energy = transform.position.y + GetComponent<Rigidbody2D>().velocity.magnitude;
}
void FixedUpdate () {
tilt = Mathf.Clamp (energy / 100, -8f, 5f);
tilt /= Time.deltaTime * 10;
if (Input.GetButton("Jump")) {
GetComponent<Rigidbody2D>().AddForce((Vector2)transform.up * Time.deltaTime * 10000);
}
transform.rotation = Quaternion.Euler(0, 0, 270+Mathf.Rad2Deg * Mathf.Atan2(rb.velocity.y, rb.velocity.x));
if (((Vector2)transform.forward + GetComponent<Rigidbody2D>().velocity.normalized).magnitude < 1.4)
tilt += 1f;
if (tilt != 0)
transform.Rotate (new Vector3 (0f, 0f, tilt * Time.deltaTime));
GetComponent<Rigidbody2D>().velocity -= Vector2.up * Time.deltaTime;
// Velocity
Vector2 vertvel = GetComponent<Rigidbody2D>().velocity - (Vector2)Vector3.ProjectOnPlane (transform.up, GetComponent<Rigidbody2D>().velocity);
fall = vertvel.magnitude;
GetComponent<Rigidbody2D>().velocity -= vertvel * Time.deltaTime;
GetComponent<Rigidbody2D>().velocity += vertvel.magnitude * (Vector2)transform.right * Time.deltaTime / 10;
// Drag
Vector2 forwardDrag = GetComponent<Rigidbody2D>().velocity - (Vector2)Vector3.ProjectOnPlane ((Vector2)transform.right, GetComponent<Rigidbody2D>().velocity);
GetComponent<Rigidbody2D>().AddForce (forwardDrag * forwardDrag.magnitude * Time.deltaTime / 1000);
airspeed = GetComponent<Rigidbody2D>().velocity.magnitude;
}
}

unity renderer.material.mainTextureOffset.x not working

Hi everybody I am having a problem with my game, the problem is based when I switch the materials so it can face the other direction (it is a 2d game). This affects the animation which is controlled by the renderer.material.mainTextureOffset but I have no idea why this is not working.
code in c#:
using UnityEngine;
using System.Collections;
public class character : MonoBehaviour {
public float forwardSpeed = 10.0f;
public Material newMaterialRefcs1;
public Material newMaterialRefcs2;
// Use this for initialization
void Start () {
}
//error is occurring here !!!!!!!! below Important. The 2 if statements below
// Update is called once per frame
void Update () {
if( Input.GetKey(KeyCode.D)){
renderer.material.mainTextureOffset = new Vector2(0.25f, 0);
transform.position += -transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs1;
}if( Input.GetKey(KeyCode.A)){
renderer.material.mainTextureOffset = new Vector2(0.25f, 0);
transform.position += transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs2;
}
}}
I'm not sure exactly what your problem is but it sounds like you're trying to adjust one setting in the first script then add a new material in the second script. If that is the case then, when you assign the new material in the second script you are replacing the material completely meaning the renderer.material.mainTextureOffset.x that you set in the first gets overwritten.
Try keeping the offset in a separate variable that you can assign to the new texture when it is added in the second script.
Try to use other shader. Diffuse, for example.
Also, check in inspector, is this value really changed. May You rewrite it in other script?
I have figured it out with some help from the unity forums took a while but here it is:
using UnityEngine;
using System.Collections;
public class character : MonoBehaviour {
public float forwardSpeed = 20.0f; public float rot = 0f;public float jumpSpeed = 100;public float gravity = 30f;
public Material newMaterialRefcs1;
public Material newMaterialRefcs2;
void Start () {
}
public float scrollSpeed = 0.25F;
void Update () {
if( Input.GetKey(KeyCode.RightArrow)){
scrollSpeed += 0.25f;
transform.position += -transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs1;
float offset = scrollSpeed;
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));
}if( Input.GetKey(KeyCode.LeftArrow)){
scrollSpeed += 0.25f;
transform.position += transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs2;
float offset = scrollSpeed;
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));
}
Vector3 isgrounded = transform.TransformDirection(Vector3.up);
if( Input.GetKeyDown(KeyCode.Space)&& Physics.Raycast(transform.position, isgrounded, 6)){
transform.position -= transform.up * jumpSpeed * Time.deltaTime*2;
}
Physics.gravity = new Vector3(0, gravity, 0);
transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z);
}
}

Categories

Resources