I'm having an issue with a prefab I'm instantiating in my script. What I'm attempting to do is simulate the physics behind the projectile motion of a cannonball. I have the following script attached to my prefab:
using UnityEngine;
using System.Collections;
public class ShootPhysics : MonoBehaviour {
// vectors & angles to be calculated
private float fx = 0f;
private float fy = 0f;
private float angle;
// forces acting upon object
private float gravity = 9.8f;
private float force = 1.2f;
// new distance & vector variables
private float dis_x = 0f;
private float dis_y = 0f;
// Script & CannonBall transform
private CannonPhysics cannon_angle;
void Start() {
cannon_angle = GameObject.FindWithTag("Gun").GetComponent<CannonPhysics>();
angle = cannon_angle.getAngle ();
fx = Mathf.Round (force * Mathf.Cos(Mathf.Deg2Rad * angle));
fy = Mathf.Round (force * Mathf.Sin(Mathf.Deg2Rad * angle));
}
void FixedUpdate() {
dis_x = (float)(fx * Time.timeSinceLevelLoad);
dis_y = (float)(fy + Time.timeSinceLevelLoad + (0.5) * (-gravity) * Time.timeSinceLevelLoad * Time.timeSinceLevelLoad);
Debug.Log (dis_x+", "+dis_y);
gameObject.transform.Translate (new Vector2(dis_x, dis_y));
}
}
And the prefab will be instantiated from the following script:
using UnityEngine;
using System.Collections;
public class CannonPhysics : MonoBehaviour {
// This will be our script to rotate our cannon
private float angle = 0f;
// cannonball object
public Transform FirePoint;
GameObject cannon = null;
void Update() {
if(Input.GetKey(KeyCode.UpArrow)) {
angle = angle + 1;
}
if(Input.GetKey(KeyCode.DownArrow)) {
angle = angle - 1;
}
// update cannon angle
transform.rotation = Quaternion.Euler (new Vector3(0, 0, angle));
if(Input.GetMouseButtonDown(0)) {
CreateCannon();
}
}
public float getAngle() {
return angle;
}
private void CreateCannon() {
cannon = Instantiate (Resources.Load("Prefabs/CannonBall"), FirePoint.position, FirePoint.rotation) as GameObject;
Destroy (cannon, 3f);
}
}
The object gets instantiated as it should, and the object is destroyed after 3 seconds as it should, however the object x
and y
position do not change at all, and are not what i should expect them to be. Let me give you an example:
These are the x
and y
coordinates i should expect which i have displaying in the console.
However these are the actual coordinates displayed in Unity's inspector:
What's strange too, is that these coordinates will not change for each object, they will literally stay the same, even after the object has been destroyed. Can anyone explain why this is happening? And perhaps offer a solution?
Edit: For a more clear example:
Each time i instantiate my cannonball object the x
and y
coordinates for the next object to be instantiated are referenced from the last. Here are the result of my first instantiated object after being destroyed.
And here they are after instantiating a second object.
Now what I'm expecting is that each new object instantiated should start from it "original" position (figuratively speaking) and the x
and y
values should reset and start again effectively.
There are a few things happening in the code you have provided in the FixedUpdate()
portion of your code which I have copied below:
void FixedUpdate()
{
dis_x = (float)(fx * Time.timeSinceLevelLoad);
dis_y = (float)(fy + Time.timeSinceLevelLoad + (0.5) * (-gravity) * Time.timeSinceLevelLoad * Time.timeSinceLevelLoad);
Debug.Log (dis_x+", "+dis_y);
gameObject.transform.Translate (new Vector2(dis_x, dis_y));
}
First, Time.timeSinceLevelLoad
provides you the time, in seconds, that has passed since your level was loaded. What this means for your code is that dis_x
and dis_y
always have larger values the longer you have your application open. So, when you spawn a new prefab, the d_x
and d_y
values are already at a position that seems as if it's using the position of the last prefab.
Instead, if you want to calculate the new position of an object given it's velocity, you'd typically want to use the deltaTime instead. For example:
dx = vel.x * Time.fixedDeltaTime;
dy = vel.y * Time.fixedDeltaTime;
In this example, dx
and dy
represent the change in position given the velocity of the object. Time.fixedDeltaTime
represents the amount of time in seconds that has passed since the last time FixedUpdate()
was called. You would then add dx
and dy
to your position to get the new position.
Secondly, gameObject.transform.Translate()
translates the position of the GameObject; it does not set the position of the GameObject. Translate will just add the Vector3 to your current position. This is why your debugging output looks so strange; dis_x
and dis_y
are not your positions; they are how far you moved the GameObject by calling Translate()
.
To set the position of the GameObject, do this instead:
gameobject.transform.position = newPosition;
...where newPosition
is a Vector3 that represents the new position of your gameobject.