I ran into a problem while making my complex(ish) camera behaviour (using Javascript). The problem that i have run to is that i am not able to get the position behind my player. Please don't tell me to use Vector3.back etc.. , because i want the position locally, to support turning. It won't work if the camera is always set to that position, cos i have a cool movement system in place.
I tried a number of approaches, and confused myself with the math. I also tried complex addition and subtraction. None of them worked at all.
I guess i am probably missing something quite simple, like a way to get into local coordinates etc.. ( or maybe a few math functions )
thanks in advance
-Etaash
You can get the forward vector of any transform, and if you negate that it is the backward vector. So on a script attached to the player you would have:
Vector3 backward = -transform.forward;
So to get a position, you could do something like this:
Vector3 pos = transform.position + (backward * dist); // where dist is a float to scale how far away from the position you want it
Related
I'm making a game where I have a skeleton as a game object:
Since this skeleton is an enemy, I want to make it walk on its own, and turn around as it reaches the edge, and so on. I managed to make it walk like so:
void Update() {
if (isWalking) {
body.velocity = new Vector2((isFacingLeft ? -1 : 1) * speed, body.velocity.y);
.
.
.
where isWalking is set to true from the beginning for testing purposes, speed is 5, and isFacingLeft is a boolean I want to flip whenever the skeleton reaches an edge, initially it is false, so the skeleton travels to the right without stopping.
So the idea I had is make use of OnCollisionEnter2D which should work since the skeleton is on top of the platform game object, and use the collision object to get different bounds:
From the picture, if the game object platform can be called L and its width y, then I'm thinking of getting the necessary bounds of it by finding Lx and Lx + y. Then, if the skeleton's width can be called x, I would want to measure the transform.position.x of the skeleton and check: if it faces right, and transform.position.x > Lx + y - x (or maybe x / 2 to approach it a bit more to the edge), then flip the isFacingLeft boolean. If it's facing left and transform.position.x < Lx + x (or x / 2), flip the boolean.
However, if I try logging the left edge (via collider.transform.position.x) and the skeleton position (via transform.position.x), I get starting values of 6.4596, 5.943441, meaning that the skeleton somehow starts before the platform. Is it possible that transform is not the right property to check for bounds in this case? How then can I ensure I'm using the desired values to check edges? If anyone knows, please comment even if you have questions about my approach, as going over the thought process really helps to get an answer.
So as suggested by pocokknight on reddit, I tried implementing ray casting, so that there is a ray projecting from a bottom corner of the skeleton sprite depending on what position it should face, achievable via SpriteRenderer.bounds.size. If the ray projected doesn't hit anything the position the skeleton would face flips. This enables the skeleton to turn around back and forth forever :)
RaycastHit2D hit = Physics2D.Raycast(new Vector2(transform.position.x + ((enemyWidth / 2) * direction), transform.position.y - enemyHeight / 2), transform.TransformDirection(new Vector2(1 * (direction), -1)), 1f);
Of course, this is a very simple execution of the function, and I could probably think of scenarios where the raycast check could fail (such as if the player object is right on its path when it should be checking for empty ground), but thus far it's a progress I'm happy with
Goal:
Calculate a rotation, that can be used, to correct the Transform of the bones, so they get rotated as expected when manually rotated.
In Detial:
Character's bone Transform is not imported to Unity correctily, ie. the left hand's Z axis does not looks towards the top of the hand, but backwards, while the right hand's Z axis looks forward.
The bones default rotation is not the same as you would expect if you have seen the rig in another application before.
I had the idea to create a class, that puts the character in T-Pose, then maps the bones rotation.
(I would assume that Unity does something similiar under the hood, that's how I got the idea.)
So the class would be used with an API like this:
/// This should return the rotation, where the bone pointing forward rotated by rotation.
/// Ie. when rotation = Quaternion.Identity the left hand should look forward.
Quaternion CorrectRotation(HumanBodyBones bone, Quaternion rotation)
{
return Quaternion.Inverse(tPoseRotations[bone]) * rotation;
}
The problem is, that I can't seem to find a good way to map theese rotations.
My last attempt was this:
Vector3 boneDirection = (boneTransform.position - parentTransform.position).normalized;
Quaternion mappedRotation = Quaternion.LookRotation(boneDirection, parentTransform.up);
As you can see in this image, with this method the hands look in the same direction, forward, but still not rotated correctly, they have an offset from the desired result. (The correct rotation is shown by the purple hands.)
When given other rotations, the hands follow with the same offset, so other then this unwanted offset they work correctly.
So basically, I would appriciate any help to fix my problem, either this way, or with a different solution, that works with different rigs.
I am trying to move my player by using rigidbody.velocity:
rigidbod.velocity = new Vector2 (Input.GetAxis ("Horizontal") * maxSpeed, rigidbod.velocity.y);
the problem is, this messes up of my explosion code. The character is supposed to be knocked back when near an explosion. I know why it happens; if the player is still, the rigidbody's X velocity would be returned as 0, meaning any outside forces pushing the player along the X axis would counteract this. So when I add the explosion, the player cuts to his new position a few units away. It looks very unnatural and jerky, as he should be pushed back, but his code is telling him to be still unless a key is pressed. I'm posting this to see if there's any way I can re-write this code to be able to move the player while being pushed correctly from outside forces. I heard that AddForce works, but when I used it, my player's velocity constantly increased. He is wither way too fast or way too slow. Any ideas on how I can get this to work? I tried adding rigidbody.velocity.x after where it says 'maxspeed' hoping that it would allow outside force input, and it works, but it messes up the movement code, making him go way too fast. I can't seem to get both the explosions and the movement code to work correctly at the same time. Any help would be greatly appreciated. Thanks.
which is exactly why in the Unity docs they explicitly state:
In most cases you should not modify the velocity directly, as this can
result in unrealistic behaviour.
instead of modifying the velocity directly, you should be using an AddForce(..)
Vector2 force = new Vector2 (Input.GetAxis ("Horizontal") * maxSpeed, 0f);
rigidbody.AddForce(force);
//or if in update:
rigidbody.AddForce(force * Time.deltaTime);
I am working with Unity 5 and making the logic of some NPC characters that will walk through a plane randomly and with animations. When the characters reaches the destination, a new target is generated after 3 seconds. The animator works fine and so does the pathfinding. Now I want the model to face forward the correct direction.
I am having a weird issue were the model does not seem to follow any conventional relation. First, it works almost fine, since the rotation is almost the one expected. The second path is deviated and after the third one is almost backwards. Is like if somehow the model were calculating the rotation related to something I have no clue.
This is part of the code I am using:
Vector3 look = targetPosition - transform.position;
Quaternion targetRotation = Quaternion.LookRotation(look.normalized,Vector3.up);
Quaternion newRotation = Quaternion.Lerp(transform.rotation, targetRotation, turnSmoothing * Time.deltaTime);
rb.MoveRotation(newRotation);
I have also tried setting the transform Euler angles, and this code:
float turnAngle = Mathf.Atan2( look.z, look.x ) * Mathf.Rad2Deg;
float smoothAngle = Mathf.LerpAngle( transform.eulerAngles.y, -turnAngle, rb.velocity.magnitude * Time.deltaTime );
rb.MoveRotation( Quaternion.Euler( 0, smoothAngle, transform.eulerAngles.z ));
Always the same result. Am I missing something? I have read about the root motion in the animator but I have disabled animations and the patter persists. Also, the model seems to have the correct Z direction set. Its driving me nuts!!
Any input is appreciated.
First of all, i want to say that you should be using Quaternion.Slerp for rotation interpolations. Lerp is a more linear interpolation wheras Slerp will make rotations seem more natural. Although i do not believe this to be the issue here.
I don't ever really use Quaternion functions, so to me your code looks fine. I can however suggest to maybe try an approach using Vector3.RotateTowards or even transform.Rotate, they should be able to get you what you are trying to accomplish here.
EDIT: I just noticed you are using rigidBody.MoveRotation after your custom Lerp interpolation. Unity API states:
Use Rigidbody.MoveRotation to rotate a Rigidbody, complying with the
Rigidbody's interpolation setting.
So, RigidBody already has its own interpolation it will try to do against your custom interpolation. The issue may lie there, because you are not setting the rotation explicitly. Try just inserting your target direction into MoveRotation and rigidbody will try and get you there. It is not an immediate rotation.
Check that your look vector is not near zero length. If you feel a root animation overwrites your rotation use simple cubes instead of NPC characters. To debug your look direction use targetRotation instead of newRotation. You can render debug lines to visualize the line NPC to target. Good luck.
I have not enough reputation points to write this as comment.
at the moment i'm working on a 2D plattformer and the work is going very well. But there is one Problem i can't get rid of.
The player can use a dash, which should move the player very fast in the direction he is looking. My problem is, that the player game object instant appears at the target location... like a teleport.
I'm using the AddForce Function to move the game object. On jumping i'm using AddForce as well and there it works really nice, i get a smooth jump movement.
The only different between dash and jump is that on jump i apply force to the y axis and on dash to the x axis. Changing the amount of force doesn't affect the movement only the distance.
Does anyone have an idea what i'm doing wrong?
// Dash
rigidbody2D.AddForce (new Vector2((dashSpeed * direction), 0));
// Jump
rigidbody2D.AddForce (new Vector2(0, jumpForce));
Best,
Verdemis :)
EDIT: I can not access my project at the moment, but i will try to show you what i have done.
Note: dashSpeed is a float value, at the moment something like 3500
and direction contains 1 or -1, depending on the direction the player is looking. The Dash code is part of the Update method.
// Dash
if(Input.GetKeyDown(dashKey))
rigidbody2D.AddForce (new Vector2((dashSpeed * direction), 0));
What is your direction vector, is it normalized? Since multiplying non-normalized vectors can be rather hazardous. Do you have more of the script to show?
EDIT: You should always do physics things in the FixedUpdate loop(link).
Ok i could solved the problem. My problem was that i only did this AddForce only once. The AddForce code was only executed in a single frame. I added a time which i count down to define how long the dash movement gonna be!
The problem may be that you are using a very big force, I was messing around with some physics today and realized that even a force of 100 almost looks instant. Try making a smaller force number to see if that helps you. I just tested making a smaller number and that does not work.