I have a Light_Spell script attached to a magic wand which is parented to a Razer Hydra hand object. The Light_Spell takes a prefab of a Light which is projected out of it when a button is pressed.
However the light is just moving up, no matter what way I rotate the hand object, it always goes up. I had it working but I changed some code around and can't remember how I got it working in the first place.
Here is the code I have so far:
//What happens when bumper is pressed
if (isSelectedSpell && SixenseInput.Controllers [0].GetButtonDown (SixenseButtons.BUMPER) && triggerIsPressed == false) {
Rigidbody instantiateProjectile = Instantiate(projectile, transform.position, transform.rotation) as Rigidbody;
instantiateProjectile.position += Vector3.down * 20.0F;
}
I have tried setting Vector3 to up and forward and a whole set of different things. Any ideas on what I should do to make it match the rotation of where the hand is pointing and stuff?
Thanks
Consider using:
instantiateProjectile.position += -instantiateProjectile.transform.up * 20.0f;
Explanation:
Vector3.down is not relative to the transform's rotation, it is a 'down' in World space, that is to say it will always be going down according to the cardinal axes.
transform.up is relative to that transform's rotation. If the projectile is rotated, the axes used to obtain "up" are rotated too. We must use an inverted transform.up instead of transform.down because no transform.down exists.
Related
So in my Unity exercise, I have to rotate a GameObject to face away from where I clicked my mouse. Also, I can only rotate around the Y-axis i.e. the GameObject is only allowed to rotate either purely to the right or purely to the left, and cannot tip towards the ground at any point. Also, I've got to do this without RayCasting (I've already done it WITH RayCasting, so as an exercise, I've got to do it without). Here's the code I've written after multiple attempts but it doesn't seem to be effective enough:
Vector3 clickLocation = Input.mousePosition;
Vector3 clickWorldLocation = Camera.main.ScreenToWorldPoint(new Vector3(clickLocation.x, clickLocation.y, transform.position.x)); //the transform.position.x is just to add some depth
transform.LookAt(new Vector3(clickWorldLocation.x, transform.position.y, clickWorldLocation.z), Vector3.up);
This code works fine if my GameObject remains in its starting position, but fails if I move it to another location and attempt the same action. Could someone help me out please?
First, call Camera.main as infrequently as you can, as it uses an expensive operation (FindGameObjectsWithTag) and doesn't cache the result.
private Camera mainCamera;
void Awake()
{
mainCamera = Camera.main;
}
To answer your question, don't use ScreenToWorldPoint in this situation, because a depth isn't most easily calculated. You don't have anything meaningful to use for the z component, and transform.position.x makes no sense here.
Instead, create a Plane that you want to click into (such as the plane parallel to the view plane and intersecting the object), use ScreenPointToRay to turn the mouse position into a Ray, then find where the ray and plane intersect. Plane.Raycast is much, much faster than a physics raycast. Then, find the direction from the mouse world position to the object, and use Quaternion.LookRotation to turn that direction into a rotation you can assign to the object's rotation:
Ray mouseRay = mainCamera.ScreenPointToRay(Input.mousePosition);
Plane mousePlane = new Plane(mainCamera.transform.forward, transform.position);
float rayDistance;
if (mousePlane.Raycast(mouseRay, out rayDistance))
{
Vector3 mouseWorldPos = mouseRay.GetPoint(rayDistance);
// make the z component of mouseWorldPos the same as transform.position
mouseWorldPos.z = transform.position.z;
Vector3 awayFromMouseDir = transform.position - mouseWorldPos;
transform.rotation = Quaternion.LookRotation(awayFromMouseDir, Vector3.up);
}
In my game I want the character to be able to have a pickaxe or weapon that can rotate around the player but when I do so it goes through the objects and is very glitchy.
I want it to still follow the mouse (which is invisible) and still stop when it has a collision. My code right now is just pretty standard code for mouse rotation and its attached to an empty gameobject which is the parent of the pickaxe/weapon
//rotation
Vector3 mousePos = Input.mousePosition;
mousePos.z = 5.23f;
Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
mousePos.x = mousePos.x - objectPos.x;
mousePos.y = mousePos.y - objectPos.y;
float angle = Mathf.Atan2(mousePos.y, mousePos.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
Whenever you have a GameObject that you want to be physics enabled, you don't move it directly. You add a Rigidbody and use RigidBody.MoveRotation to rotate your GameObject. RigidBody has its set of movement and rotation methods that take into account collisions. Moving the Transform directly will cause problems.
This can still cause problems in some situations. If you're still experiencing physics weirdness then you can eliminate them by using a "physically correct" solution and use Rigidbody.angularVelocity. Based on the angle you can set the velocity to either rotate the object right or left until it faces the way you want.
Essentially the physics system hates teleportation. Instant movements and instant rotations are basically teleportation to it. So there's a hierarchy of how "physics system friendly" some actions are. And they go like this:
Adding Force to the RigidBody
Adding Velocity to the RigidBody
Moving the GameObject through appropriate RigidBody methods.
Moving the GameObject through Transform.
I am working in unity trying to make a space shooter while watching the tutorial. The bolt is supposed to move on the z axis but it falls instead, and the ammo is not using gravity.
rb = GetComponent<Rigidbody>();
rb.velocity = transform.forward * speed;
what you see above is what the instructor told me to put into the script.
For the movement in the z axis, if the rotation of the bolt is zero in each of the vectors of the transform and it doesn't have a parent with any other non-zero rotation it should move in unity's z axis correctly with transform.forward. If that doesn't work then, instead of transform.forward you could use Vector3.up, or Vector3.forward instead.
The forward vector is the blue one in Unity editor. Check that your bolt goes in the direction of the blue arrow. It it doesn't, check that you correctly disabled gravity in the rigidbody of this object (be sure it is the right one). In the same way, be sure that you added your script in on the right object.
If you still can't figure out what goes wrong, give us more precision. Does your projectile go in a straight line, or is it still affected by gravity? What happens if you change the speed value, doesn't it work?
This is likely a problem in the setup in Unity's editor. The script is fine so we can't really know more without seeing the editor
I'm still learning the basics so please be a bit gentle. I'm working on the movement script of a roll-a-ball game. I've got the rolling around working perfectly fine, but now I'm trying to add the ability to jump.
In my case the "player" is a basic Sphere. What I'm trying to accomplish is that when space is pressed, the ball leaps into the air in the direction it's currently rolling.
This is what I've tried myself, but gave very strange results:
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
if (Input.GetKey("space"))
{
transform.position += transform.up * 20 * Time.deltaTime;
}
rb.AddForce(movement * speed); //rb = RigidBody
This resulted in the ball sometimes jumping in the wrong direction or simply just speeding into some direction without jumping at all. So obviously I'm getting closer, but not quite there yet. Could anyone explain what I'm doing wrong and how to fix it?
Not looking for a quick fix! Don't learn anything from that.
Have a try at this :)
if (Input.GetKey("space"))
{
rigidbody.AddForce(new Vector3(0, yourJumpForce, 0), ForceMode.Impulse);
}
You also might want to fiddle with the gravity settings in the rigidbody to get your desired jump as well!
EDIT Explanation:
I think it may be because you are applying you movement to your Rigidbody, but your jumping method to the Transform itself.
A Rigidbody is a physics component (see docs.unity3d.com/ScriptReference/Rigidbody.html), where a Transform is to do with position, rotation and scale.
A jump could be considered a physics problem - therefore altering the jump is to do with physics (Rigidbody), not the position (Transform). I tend to do all movement code with the Transform, as you are moving positions, and do all physics based work with the Rigidbody, as you are applying physics to the GameObject! :)
To add to the accepted answer: The jumping into random directions issue could have been caused by the transform.up. That vector is the up direction relative to your current transform. That's usually the same as the actual up direction, except if you rotate the game object. And as the object happens to be a rolling ball in this case, it's very likely that it's rotated.
You can fix it by using the global up direction instead - either by doing it like in the accepted answer or by using Vector3.up.
My gameObject does not rotate while jumping. I used GetComponent().rotation = Quaternion.identity; for rotation but the gameObject still does not rotate. What is the problem? And how do I adjust the speed of the rotation? Here's my jump script:
Quaternion.identity means no rotation {0,0,0,0}, whenever this code block is called the gameObject's rotation will become the standard rotation value.
If this was intentional and the rotation of the gameObject is not {0,0,0,0} then perhaps you are modifying the rotation elsewhere?
GetComponent().rotation = Quaternion.identity;
Couple issues with this line. First off, just use transform.rotation... no need to call GetComponent() here. Also, Quaternion.identity is just the 'zero' rotation. What kind of rotation are you actually trying to apply here because you shouldn't see anything using identity.
http://docs.unity3d.com/ScriptReference/Quaternion-identity.html
To apply real rotation use something like (where "speed" is a float var where you can set how fast you want your cube to rotate):
transform.Rotate(Vector3.up, speed * Time.deltaTime);