I'm currently using this code:
public Transform Target;
public float speed = 20f;
public GameObject ME;
private void Update()
{
if (Vector3.Distance(ME.transform.position, Target.transform.position) < 5)
{
Vector3 direction = Target.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(-direction);
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, speed * Time.deltaTime);
}
}
Pretty much what it's doing is rotating an object based on where the target is. So if the target goes to the right the object is always facing it.
Now, I'm trying to achieve something like in this video, I'm trying to add edge fixed objects, where they rotate based on where the target is, but one of the edges is fixed to the wall, almost like a page in a book. I've found code to use another object, and use that as a pivot point, but I was hoping for a more straightforward solution that will allow me to use a boolean. For example, if the edge was on the right, rightFixed would be true, if left then leftFixed would be set to true. I figured moving the pivot point would be simplest solution, but now I am not exactly sure... how could I get that sort of functionality implemented?
Huge thanks for any help guy!
Related
Basically I am looking for a simple way for using the rigidbody/physics engine to have my ship look at another object (the enemy). I figured getting the direction between my transform and the enemy transform, converting that to a rotation, and then using the built in MoveRotation might work but it is causing this weird effect where it just kind of tilts the ship. I posted the bit of code as well as images of before and after the attempt to rotate the ship (The sphere is the enemy).
private void FixedUpdate()
{
//There is a user on the ship's control panel.
if (user != null)
{
var direction = (enemyOfFocus.transform.position - ship.transform.position);
var rotation = Quaternion.Euler(direction);
ship.GetComponent<Rigidbody>().MoveRotation(rotation);
}
}
Before.
After.
Well the Quaternion.Euler is a rotation about the given angles, for convenience provided as a Vector3.
Your direction is rather a vector pointing from ship towards enemyOfFocus and has a magnitude so the x, y, z values also depend on the distance between your objects. These are no Euler angles!
What you rather want is Quaternion.LookRotation (the example in the docs is basically exactly your use case ;) )
var direction = enemyOfFocus.transform.position - ship.transform.position;
var rotation = Quaternion.LookRotation(direction);
ship.GetComponent<Rigidbody>().MoveRotation(rotation);
I am trying to get a car to move by itself in Unity (C#). I can get the car to travel forwards by using:
transform.position += transform.forward * Time.deltaTime * speed;
However, I'm not sure how to get the car to turn. I would like it to behave in the following way:
Imagine a car enters a cross roads (square of size 1x1 and negligible height) at point (0.5,0,0), i'd like it to exit the cross road at point (0,0,0.5) by simulating the turning of the vehicle in a circular pattern.
Does anybody know how to do this? I am getting problems with my mathematics.
As always, all help is appreciated :).
First of all you gotta detect the car position >
> if (car.transform.position == 'WANTED POSITION') {
while(car.transform.position.WANTEDSCALE != 'WANTED ROTATION'){
car.transform.Rotate (new Vector3 (0f, 0f, 'ROTATION SPEED' )); //rotatesZ
}
}
WANTEDPOSITION = VECTOR 3 (0.5,0,0) as you wanted it
WANTEDSCALE = X/Y/Z = i dont know which one of them you want to rotate(probably z)
WANTED ROTATION = the rotation you would like to be at the end of the 'autopilot'
ROTATION SPEED = rotates at the speed you want... put it low and go testing until a number you want comes
Sorry for not coding everything right now... i just gave you the all logic... hit me up if you have any doubts or send me the whole code and maybe i will adjust it for you
I'm trying to add knockback to my player, but he won't move. I know the function is correctly called and the if a statement is functional, as he will still take damage, but the player won't move at all.
Weirdly, if I put the addForce somewhere else (Like in the update() method), it will work, but not in this scenario.
Some help would be greatly appreciated
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Enemy")
{
TakeDamage(-20, 21);
theRB.AddForce((collision.transform.position - transform.position).normalized * 100, ForceMode2D.Impulse);
}
}
Here is what the Rigidbody looks like if it helps:
Hey I think the issue here is with your use of
(collision.transform.position - transform.position)
I would instead calculate the direction using the contact point of the collision and save that in a Vector. Then normalize that vector and multiply by -1 to launch the player in the opposite direction. Here's some sample code:
Vector2 dir = collision.contacts[0].point - transform.position;
// Flip the vector and normalize
dir = -dir.normalized;
// Apply Force
theRB.AddForce(dir * 100, ForceMode2D.Impulse);
Ok, so I figured out the answer. The problem lies in the way I managed movement in my Movement() function. To create movement, I used this line :
theRB.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized * playerSpeed;
Apparently, velocity doesn't really work well with AddForce, for reasons I am not capable of explaining, as my understanding of Unity is still limited. I'll need to figure out a better way to manage movement, and I'll edit this post once I figure it out in case someone made the same mistake as me.
EDIT : So, turns out I've been looking for weeks, and didn't find anything. My final solution was to use a LERP instead of Addforce(), and just forget about physics alltogether.
I need the Player to follow the moving Target and stop exactly when it reaches the Target.
The Player has to reach the Target almost instantaneously in every frame, so i need a high speed way to do it.
I couldn't use Transform.translate because there's a lot of physics implementations in my game and using Transform.translate or movetowards made the physics buggy.
Is there any physics based way to follow the target? velocity, AddForce, anything? For a 2D game.
Any leads would be greatly appreciated! Thank You!
If you have a Rigidbody2D you want to follow another object, the Rigidbody2D.MovePosition is the proper way to move it.
Do the following:
1.Disable gravity by setting the "Gravity Scale" to 0.
2.Change the BodyType to Kinematic.
3.You can now move the Rigidbody object to follow another GameObject with the Rigidbody2D.MovePosition function. See code below. This should be done in the FixedUpdate function and with Time.fixedDeltaTime instead of Time.deltatime.
Finally, if you still get jerky movement, change Interpolate option from None to Interpolate or Extrapolate. I would also suggest reducing the speed variable below.
//Object to follow
public Transform target;
//Rigidbody to move
public Rigidbody2D rb2d;
public float speed = 7.0f;
//Distance to start moving
public float minDistance = 0.09f;
void FixedUpdate()
{
//Find direction
Vector3 dir = (target.transform.position - rb2d.transform.position).normalized;
//Check if we need to follow object then do so
if (Vector3.Distance(target.transform.position, rb2d.transform.position) > minDistance)
{
rb2d.MovePosition(rb2d.transform.position + dir * speed * Time.fixedDeltaTime);
}
}
Changing the velocity directly is always a bad practice and should be avoided. Instead always work with AddForce.
I would calculate the distance between the target and the body and add a force based on that distance.
var dif = target.transform.pos - body.transform.pos;
bodyRigid.AddForce(dif * multiplier * Time.deltatime);
The only problem that comes with that solution might be the fact that the body 'shakes' around the target once its to close.
You could avoid this by checking if the body is close to target and then freezing it.
var dif = target.transform.pos - body.transform.pos;
if(dif.magnitude > 1) {
bodyRigid.AddForce(dif * multiplier * Time.deltatime);
} else {
bodyRigid.velocity = Vector2.zero;
}
Although I said that setting the velocity directly is a bad habit, using it to just freeze the body should be fine. I have no idea whether that might break your other physics that you use in your game, duo the fact that that just strait up freezes your object.
You can also change the distance (1 in the if statement) that it needs in order to freeze, just play around with it a bit and find a value that fits the game
I have a floating gameobject (brickRot) that looks at what object is beneath it through a raycast, and then changes that object's y-position (floorY) based on brickRot's rotation. However, I'm having trouble converting rotation into a useful metric for changing Y-position. I want the current rotation of brickRot to be equal to whatever the y-position of floorY is, and then only change relative to the rotation of brickRot (if that makes any sense).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FloorRotation : MonoBehaviour {
private float brickRot;
private float floorY;
void Update () {
brickRot = transform.rotation.y;
RaycastHit hit;
Ray floorRay = new Ray(transform.position, Vector3.down);
if(Physics.Raycast(floorRay, out hit)) {
if(hit.collider.tag == "floor") {
floorY = hit.transform.position.y;
floorY = floorY + brickRot;
Debug.Log(floorY);
}
}
}
}
Think of brickRot as a plate you put down on the table, and when you rotate the plate, you change the table's y-position (if that analogy makes it any less confusing). The reason why I'm using a raycast is because there are multiple "tables" that the brick can find, and it needs to differentiate between them. If anyone has an idea of how to make this any easier, I would be forever thankful!
The rotation values you get are in Quaternion angles, not the common 360 degree Euler rotations. Unity, or any other game engine, uses Euler only for representation for us, but it never uses it internally for any sort of rotation calculations.
I am going to suggest not delving into deeply understanding Quaternions. But instead, think of how else you could achieve it.
For a suitable metric, add a child gameobject, rotated by 90 in x or y or z(check this, it depends on how you've oriented your parent) and some distance away from parent, to brick gameObject. Now when you rotate the brick, the child will automatically move in y, following a circular movement around the parent. You can use the child's Y as a metric for updating floorY.
use "eulerAngles" value instead , it'll convert the quaternion to an vector3
then you use angle function of vector3 to get some float, you can multiply the float with another value if you need bigger/lower scale
brickRot = angle = Vector3.Angle(transform.rotation.eulerAngles, transform.forward);