I’m a total noob here, but I’ve searched the forum and couldn’t find this addressed anywhere. I’m following the tutorials, as well as other examples I’ve seen on the forums, where projectiles are fired in one of the following ways:
I’ve attempted both methods having attached the above code to my camera object and the object I’m “firing” behaves correctly EXCEPT it won’t travel in the negative X direction. It’s very strange. It will go exactly where I aim unless I’m aiming toward the negative X. In which case, the velocity of the object seems to be calculated correctly except that it is as if the .x component where simply set to 0.
Can anyone explain what I am doing wrong? Thanks a bunch in advance!
transform.forward should give you that transform’s forward direction vector (world-relative), whether that has a zero x-component or not. Perhaps you can share more of your code with us (like the actual code you’re using)?
And welcome to the forums! So many new users these days, it’s great!
Thanks for the quick reply! Here’s the full script:
var CannonBall : Rigidbody;
var speed = 30.0;
function ShootCannon ()
{
var cannonBallClone : Rigidbody = Instantiate(CannonBall, transform.position, transform.rotation);
cannonBallClone.velocity = transform.forward * speed;
}
// Calls the fire method when holding down ctrl or mouse
function Update ()
{
if (Input.GetButtonDown("Fire1")) {
ShootCannon();
}
}
That is attached to my Main Camera. And it works just fine so long as the local Z is pointing in a positive X direction (world space). It is exactly like the above code is clamping the X component to >0. The camera starts out looking straight down the positive Z (world space). If I shoot from that stance, it works. I can turn to the right (now aiming in the positive X) and it works. But if I turn to the left, the cannon ball continues to shoot straight down the positive Z. The velocity of each shot gets slower the more directly I point to the negative X - exactly as if it was clamping the X velocity component to 0. I can continue turning left, and once I complete a 180 degree turn (now facing in the negative Z), it starts working fine again.
I hope that detailed description of the behavior helps. It is rather strange so I understand if it is still not very clear.
Your script works perfectly fine on my end, there are no limitations with what direction I can shoot an object. Do you have anything else in the scene that might be causing a problem?
Not that I can figure. I’ve tried this in a couple of different scenes and have gotten the same behavior. The only other objects in the scene are:
a collection of (lots of) meshes with rigid bodies
Main Camera
Plane (for the ground)
Spot light
The Main Camera is what has the script attached to it. The camera also has the following built-in scripts (unmodified) attached:
Mouse Look
FPSWalker
Character Controller (I think this was added by FPSWalker)
I tried disabling both FPSWalker and Mouse Look (and then just manually rotated the camera in the scene editor) but received the same behavior.
I’m using the indie trial (will probably be going Pro in the next couple of weeks) if that could have anything to do with it.
One interesting thing is that if I strafe to the left and fire, the balls will travel in the negative X, but I think that’s just the “inherited” velocity from the movement of the camera, but they won’t travel in the negative X as a result of my aiming.
Is there anything more bare-bones I could try to see if I can isolate the problem?
Nope, trial versus Indie versus Pro wouldn’t matter here. In my scene I had:
First person character controller (with those default scripts)
I attached your script to the camera found as part of that controller
I created a simple sphere rigidbody prefab, I drag assigned that as the CannonBall
There is a large flat plane
I can spin in circles and fire in every direction I want.
It sounds like you’re at the simple stage already. If you’d like, either post or send along an exported package file for folks to test. Save your scene, then select the scene file and right/ctl-click the scene and export the package file.
Or check out the package file I just uploaded, it’s small and has minimal lighting, but if you play it and look at the Scene view and Game view you can see that you should be able to fire in all directions.
Thanks to your sample, I’ve identified the critical difference between our projects:
I took the “Main Camera” that comes with a brand-spankin’ new scene and simply added the FPSController script to it as a component (as well as Mouse Look). I then added my “shooting” script. This resulted in the bad behavior I was experiencing (though I still don’t understand why).
By contrast, I figured out that you actually used the “First Person Controller” Prefab found in the Standard Assets->Prefabs folder. I replaced my Main Camera with this prefab and then attached the shooting script to the “Main Camera” child object under the “First Person Controller” in my Hierarchy. This worked perfectly!
I hate to be a nuisance, but being new to Unity I’d appreciate it if you could explain why what I did was wrong and why it resulted in the behavior I experienced?
Thanks again! You’re the best. I really, REALLY, appreciated your unbelievably quick responses. You guys are awesome. I now know that my choice to go with Unity was absolutely unquestionably the right one.
Well, as it turns out, that fixed the X-axis problem, but now even using the sample scene you sent, it appears that the projectile will not “aim” along the negative Y-axis. If you place your camera on top of an object, walk up to the edge so you can fire downward and then aim as far down as possible and shoot, you’ll notice that the projectile still shoots straight out in front of you. The further you aim downward, the slower the projectile will go (as if the Y-component is being clamped to 0), but it won’t actually “fire” downward along your look vector.
The strange thing is, I checked the value of the velocity of the projectile immediately after it is assigned in the script and it shows what I presume to be the correct Y component. But somewhere along the line, it looks like its getting clamped. Try this in your test scene to see what I’m referring to.
And so I figured out the reason for this in my example project and it’s easy to fix. Once I sorted it out it was a bit of an “oh duh” moment…
The character controller is rigid body as that’s how it stays grounded with the surface below it. The trouble with the script and the way it’s used in my demo is that it spawns the cannon ball at the same location as the camera, which is just inside the top “dome” of the character controller’s pill shape. As soon as you do that you get an instant collision between the cannon ball and character controller, the result of which is that the ball cannot leave on a downward track (it will be in the flat plane of y=0, or upwards only).
The solutions are:
Disable/ignore collisions between your cannon balls and the character controller using something like IgnoreCollision. Example (your script, modified in my project to ignore collisions with the camera controller:
var CannonBall : Rigidbody;
var FPController : Transform;
var speed = 30.0;
function ShootCannon ()
{
var cannonBallClone : Rigidbody = Instantiate(CannonBall, transform.position, transform.rotation);
Physics.IgnoreCollision(cannonBallClone.collider, FPController.collider);
Debug.Log(transform.forward);
cannonBallClone.velocity = transform.forward * speed;
}
function Update ()
{
if (Input.GetButtonDown("Fire1")) {
ShootCannon();
}
}
Make sure to drag-assign the First Person Controller from your Hierarchy view to assign it as the FPController variable’s value.
The second solution is to instantiate the cannon ball outside of the character controller capsule, thus avoiding any collision to begin with. This is easily done by adjusting the position vector provided when you call Instantiate:
var CannonBall : Rigidbody;
var speed = 30.0;
function ShootCannon ()
{
var cannonBallClone : Rigidbody = Instantiate(CannonBall, (transform.position + transform.forward), transform.rotation);
Physics.IgnoreCollision(cannonBallClone.collider, FPController.collider);
Debug.Log(transform.forward);
cannonBallClone.velocity = transform.forward * speed;
}
function Update ()
{
if (Input.GetButtonDown("Fire1")) {
ShootCannon();
}
}
Modify my demo on your end, then I’m sure you can modify yours to work as well. Sorry it took so long to get back to this and give it a closer look!
Thanks SOOO much for this extremely thorough explanation of both the problem and the multiple solutions. That explanation makes perfect sense now that you point it out. Both the solutions work perfectly and I really appreciate it!
I now have it working exactly as it should. Thanks again!
i tried putting that script for my racing game and it didn’t work. Any ideas? its from a third person view which might be a problem but I’m trying to do a projectile system like Mario Kart
For a third-person game, I’d spawn the projectile at the car rather than at the camera. I’d get the position of the car (<car_variable>.transform.position) and then use one of the solutions mentioned earlier (ignoring collisions or moving the starting point of the projectile to be outside the car mesh).
First, make sure you aren’t instantiating the object inside the bounds of any collider. That was my problem when I was spawning my projectile from within the character collider attached to the camera. It had to be offset so that it started outside the collider.
Second, it doesn’t seem to me that that script should compile. newObject is of type Transform which I don’t think has a velocity member. Make sure you are assigning the velocity to a Rigidbody. See my script above.