- Home /
Help! My projectile just falls to the ground :(
Ever since I started to add networking to my script I am having a problem with firing my arrow.
I have an arrow prefab and two scripts, the arrow script which goes on the arrow, and the shootArrow script which goes on the player. Now all was well and good until I added multiplayer. Now, while playing online my characters can not see eachother's arrows flying. They see it instantiate, but then it just falls to the ground in front of them on their screen.
So I read in some other threads that instead of adding force when the arrow is instantiated (in the shoot arrow script), to add force in the awake or start function on the arrow itself. OK - no problem so I have done that. but now the arrow doesnt even shoot on my screen.
Whats odd is when I change it from addforce in the start function to transform.translate in the update function,it works, AND the other player can see it! But I really want to use add force for obvious reasons.
How can I get add force to work? Here is my script called Arrow, that is on the arrow. You will see my addforce at the beginning, but no force seems to be added.
using UnityEngine;
using System.Collections;
//script description:
//this script is attached to the arrow prefab and governs the behavior of the arrow.
//Accesses the spawn script
//Accessed by the ShootArrow script
public class Arrow : MonoBehaviour {
private Transform myTransform; //caches transform of arrow
private int expireTime = 60;
private float range = 0.5f;
private RaycastHit hit;
//Used for hit detection
public string team;
public string myOriginator;
public float arrowPower = 100;
public float speed = 100;
void Start ()
{
rigidbody.AddForce(Vector3.forward * speed);
//As soon as arrow is created start the countdown to destory in after "expireTime" seconds
StartCoroutine(DestroyMyself());
myTransform = transform;
}
void FixedUpdate ()
{
//if I use this it works: myTransform.Translate(Vector3.forward * 10 * Time.deltaTime);
if(Physics.Raycast(myTransform.position, myTransform.forward, out hit, range))
{
rigidbody.isKinematic = true;
if(hit.transform.tag == "BlueTeam" || hit.transform.tag == "RedTeam")
{
//Access the HealthAndDamage script of the enemy player and inform them that they have been attacked and by whom
if(hit.transform.tag == "BlueTeam" && team == "red")
{
HealthAndDamage HDscript = hit.transform.GetComponent<HealthAndDamage>();
HDscript.iWasJustAttacked = true;
HDscript.myAttacker = myOriginator;
HDscript.hitByArrow = true;
}
if(hit.transform.tag == "RedTeam" && team == "blue")
{
HealthAndDamage HDscript = hit.transform.GetComponent<HealthAndDamage>();
HDscript.iWasJustAttacked = true;
HDscript.myAttacker = myOriginator;
HDscript.hitByArrow = true;
}
}
}
}
IEnumerator DestroyMyself()
{
//Wait for the timer to count to expireTime then destroy the arrow
yield return new WaitForSeconds(expireTime);
Destroy(myTransform.gameObject);
}
}
And here is the sniped from shootArrow where I instantiate if you need that as well:
public void Shoot(float power)
{
launchPosition = cameraHeadTransform.TransformPoint(0,0,0); //where to launch arrow from
//instantiate arrow and add force to it based on the amount of power
//make the arrow team specific.
if(iAmOnTheRedTeam == true)
{
networkView.RPC("SpawnProjectile", RPCMode.All, launchPosition, Quaternion.Euler(aim.eulerAngles.x - 5, myTransform.eulerAngles.y, 0), myTransform.name, "red");
}
if(iAmOnTheBlueTeam == true)
{
networkView.RPC("SpawnProjectile", RPCMode.All, launchPosition, Quaternion.Euler(aim.eulerAngles.x - 5, myTransform.eulerAngles.y, 0), myTransform.name, "blue");
}
}
[RPC]
void SpawnProjectile (Vector3 position, Quaternion rotation, string originatorName, string team)
{
GameObject myArrow = Instantiate(arrow, position, rotation) as GameObject;
//myArrow.rigidbody.AddRelativeForce(Vector3.forward * power);
//Access the Arrow script on instantiated arrow and supply players name and team.
Arrow bScript = myArrow.GetComponent<Arrow>();
bScript.arrowPower = power;
bScript.myOriginator = originatorName;
bScript.team = team;
}
}
Quick update - if I put the addrelativeforce line in the update function, the arrow will shoot but the other player cant see it argg! lol. If I put it at the Start() then it doesnt fire at all. If I use transform.translate in the update - it shoots and the other player sees it. But it looks like crap I need to use add force - just dont get it! :(
Answer by AlucardJay · Nov 27, 2012 at 06:45 AM
The problem is you want to add an instantaneous force, where AddForce is applied over time in physics. For an instantaneous force in your case of hitting the jump button once, you need to use ForceMode.Impulse :
rigidbody.AddForce( transform.forward * speed, ForceMode.Impulse );
also note the difference between Vector3.forward and transform.forward . I assume you want the bullet to travel in the direction that it is facing ( transform.forward ) and not just forward in world-space along the +ve Z_axis ( Vector3.forward )
Links :
http://docs.unity3d.com/Documentation/ScriptReference/Rigidbody.AddForce.html
http://docs.unity3d.com/Documentation/ScriptReference/ForceMode.Impulse.html
You can do this either when the bullet is Instantiated, or in the bullet Start/OnEnable function. Both will give you a multiplied result.
So, edit the above line into the bullet Start function, or in SpawnProjectile after the Instantiate :
GameObject myArrow = Instantiate(arrow, position, rotation) as GameObject;
myArrow.rigidbody.AddForce( transform.forward * power, Force$$anonymous$$ode.Impulse );
Thank you both very much, I will try this asap. As far as from a network standpoint, which would Be better, Using the start function or adding force immedietly after instantiate?
I thought I read that that if using multi player you should add force in the start or awake function but I might not have understood correctly.
I havn't done anything with networks so cannot answer that. But have been learning to base my script on OOP (Object Orientated Program$$anonymous$$g) , that basically means everything looks after itself.
So for example, a bullet does what a bullet does, fly forwards and hits things. If it were my project, I would have the bullet propel itself forward as soon as it exists.
Then if you ever want to use your bullet in another project, the prefab is already made, just instantiate it, and you don't have to remember to add force to it when you do instantiate it, as soon as the bullet exists, it flys forwards =]
For just a bullet it doesn't matter so much, but when you have more complex stuff like AI enemies, then all you want to tell it when you instantiate/enable an object is where (position and rotation), the object from there should take care of itself. Happy Coding =]
Good point - also ITS WOR$$anonymous$$ING!! Thanks guys very much. Now if I could just figure out my null reference error I could move forward with my life!! Lol.
I shall look at that question, btw I'm $$anonymous$$ $$anonymous$$ay (I couldn't work out Thanks guys very much! click on the name and you'll see the profile page is the same. Name appears in questions/answers and handle appears in comments. I cannot change it as the handle is the username).
=]