I'm making a 2.5D plataform game and I can't get the rotation of the player right. I just want it to rotate on the X-axis while the player move towards left and right. My movement script is this:
if (isWalking)
{
transform.Rotate(0, facingDir, 0);
isWalking = false;
}
else { }
if (Input.GetKey(KeyCode.Space))
GetComponent<Rigidbody>().velocity = new Vector2(GetComponent<Rigidbody>().velocity.x, jumpHeight);
if (Input.GetKey(KeyCode.A)){
GetComponent<Rigidbody>().velocity = new Vector2(-speedHeight, GetComponent<Rigidbody>().velocity.y);
facingDir = 180;
isWalking = true;
}
if (Input.GetKey(KeyCode.D))
{
GetComponent<Rigidbody>().velocity = new Vector2(speedHeight, GetComponent<Rigidbody>().velocity.y);
facingDir = 0 ;
isWalking = true;
}
The best way I could rotate it was by transform.rotate(0,180,0) and (0,0,0), but then it keeps rotating non stop, how can I tell what direction the player is moving on the X-axis so I can transform.rotate properly?
transform.forward
This should give you the direction the player is moving in. You can use
transform.LookAt(target);
to orient the player in a specific direction. The main issue is that you are trying to update the direction in the GetKey function which returns true while the key is held down. This results in the character rotating constantly, you have avoided this by using an additional check. You could use Lookat instead in the following manner:
GetComponent<Rigidbody>().velocity = new Vector2(-speedHeight, GetComponent<Rigidbody>().velocity.y);
transform.LookAt(transform.position+new Vector3(GetComponent<Rigidbody>().velocity.x,0,GetComponent<Rigidbody>().velocity.y));
There are better ways to do this but this should solve your problem.
Related
I've searched around and can't seem to find a write up on the calculations I might need for placing an object onto another one without them placing halfway inside of eachother.
private void MovePlaceableObject()
{
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
Debug.DrawRay(ray.origin, ray.direction * 20f);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 15f))
{
Vector3 newPosition = hit.point;
currentPlaceableObject.transform.position = newPosition; //move object to where we have the mouse
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal); //rotation equal to the current rotation of our hitinfo, then up
}
}
private void HandeNewObjectHotkey()
{
if (Input.GetKeyDown(newObjectHotkey))
{
if(currentPlaceableObject == null)
{
currentPlaceableObject = Instantiate(placeableObjectPrefab);
//currentPlaceableObject.GetComponent<BoxCollider>().enabled = false;
}
else
{
Destroy(currentPlaceableObject); //pressing the button again will destroy current object
}
}
}
I've tried storing the object I'm looking at's size to floats for x,y,z and a vector3 for it's position, and tried fiddling around with adding those to the newPosition with the hit.point to no avail.
I've wracked my brains for about a day now, i'm terrible at math, however I know that you must need to get the current object your looking ats position or size, then factor that into your placement right?
Get the size of the object that you are looking at by accessing its collider component. You can use the bounds property of the collider to get its size.
Bounds objectBounds = hit.collider.bounds;
Calculate the center point of the object by adding half of its size to its position.
Vector3 objectCenter = hit.collider.transform.position + objectBounds.extents;
Calculate the position of the new object by adding the size of the new object to the center point of the object that you are looking at. This will place the new object on top of the other object.
Bounds newObjectBounds = currentPlaceableObject.GetComponent<Collider>().bounds;
Vector3 newObjectPosition = objectCenter + new Vector3(0, newObjectBounds.extents.y, 0);
Set the position of the new object to the calculated position.
currentPlaceableObject.transform.position = newObjectPosition;
You can also set the rotation of the new object to match the normal of the surface that it is being placed on, as you are already doing in your code.
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
I'm struggling a lot with moving Rigidbodies, currently I have this method to move player:
private void SimpleMove()
{
var scaledMovementSpeed = movementSpeed;
_isRunning = false;
if (Run)
{
scaledMovementSpeed *= runMultiplier;
_isRunning = true;
}
var trans = transform;
var forward = trans.forward;
var newDirection = Vector3.RotateTowards(forward, SimpleMoveVector, Time.fixedDeltaTime * rotationSpeed, 0.0f);
trans.rotation = Quaternion.LookRotation(newDirection, trans.up);
var velocity = _rigidbody.velocity;
var velocityChange = new Vector3(forward.x * scaledMovementSpeed, velocity.y, forward.z * scaledMovementSpeed) - velocity;
_rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);
_isMoving = true;
}
Map is build out of simple cubes right now and the player has capsule collider on him with freeze rotation on all axes.
By tweaking force values a little bit I managed to get it to work properly without the need to check for collisions myself but
expected behavior of player going diagonally into wall is to slide perpendicular to its surface. When I get close to cube's corner character slides across but when I'm going diagonally into a wall character just stops. Haven't tried it with analog input yet.
Is there a way to properly make character slide (fe. put proper physics material on him, or the wall?) or do I need to explicitly check and manage these collisions myself for that?
I thought that my turn-and-then-go-forward method might be messing with proper colliding, but I made the turn instant and the behavior was exactly the same.
I'm trying to do a little game on mobile using Unity and I've got a problem with the rotation of a maze.
To add context :
When your moving your finger on the screen, the maze is rotating on himself. There is a ball in it and you need to make it go on a cell to win the level.
When the maze is rotating too fast, the ball falls down and go through the ground and I don't know how to fix it.
I tried to play with the gravity, colliders...
This is the same when the ball is jumping (when the maze is going up and down quickly).
For the moment I just reset the ball position when you're falling.
{
ball.transform.position = new Vector3(0, 2, 0);
maze.transform.position = Vector3.zero;
maze.transform.rotation = Quaternion.identity;
}
Do you guys have some ideas ? Thanks
I had a similar problem in a tilt maze mini-game I worked on. Ideally implementing jkimishere's solution will work but I assume the maze is moving too fast for the collisions to register properly. You'll need to smooth the maze's rotation with a Lerp. In our case we had pressure plates with a tilt value, so it doesn't directly translate to your mobile use but perhaps give you a nudge in the right direction. We used:
public GameObject maze;
private float _lerpTime;
private bool _isRotating;
private Quaternion _startingRot, _desiredRot;
private void Awake()
{
_startingRot = maze.transform.localRotation;
}
private void Update()
{
//Don't want to move the maze if we don't ask for it
if(!_isRotating)
return;
//Lerp the maze's rotation
_lerpTime = Mathf.Clamp(_lerpTime + Time.deltaTime * 0.5f, 0f, 1f);
maze.transform.localRotation = Quaternion.Lerp(_startingRot, _desiredRot, _lerpTime);
//Once the maze gets where it needs to be, stop moving it
if(affectedObject.transform.localRotation.Equals(_desiredRot)
_isRotating = false;
}
private void ActivateTilt()
{
//Set the new starting point of the rotation.
_startingRot = maze.transform.localRotation;
//However you want to calculate the desired rotation here
//Reset our lerp and start rotating again
_lerpTime = 0f;
_isRotating = true;
}
This will ease the rotation of your maze over time. So that the ball can adapt to the new collider positions.
In the rigidbody(for the ball), make the collision detection to continuous, and in the rigidbody for the maze(if you have one) set the collision detection to continuous dynamic. Hope this helps!
I think that is unavoidable if you allow the player to move the platform freely. I suggest you restrain the speed at wich the player can tilt the platform. This way, the ball will have more frames to adapt to the new slope
i wanna build a Jumppad in my Unity Platformer game (2D).
I thought it will be easy if i just add a Addforceor velocity if my player collides with the jumppad, but there is a problem.
instead of flying in a 45° angle, my pleyer first gets pushed all the way in the direction of the X-Axis, and after in the direction of the Y-Axis.
the bool sprungFlächeBerührt gets true if the player collides with the Jumppad
if(SprungFläche.sprungFlächeBerührt)
{
rb.velocity = new Vector2(10f, 10f);
SprungFläche.sprungFlächeBerührt = false;
}
Quite strange. Might be a bug. Try this:
rb.velocity = new Vector3(10f, 10f, 0f);
First that is a 2D game.I made a rotating water mill. When I put my character on top of that. Character does not rotate like it should. It does not turn with water mill and trying to save its position. How can I fix it?
I tried to add Physic materials and some effectors.
////Thats movement code
void FixedUpdate()
{
if( (Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow)) && OnPlatform )
{
OnPlatform = false;
rb.velocity = Vector2.up * JumpForce;
}
float move = Input.GetAxisRaw("Horizontal") * MovementSpeed;
if( canWalk && move != 0 )
{
rb.velocity = new Vector2(move,rb.velocity.y);
}
}
I want my rotating surface and player rotate normal like in real world.
One solution would be to make the player a child object of the water mill while he stands on it. But that he then no longer is a child object of it when not standing on it.
Child objects get affected by their parents rotation, scaling and position. So this would rotate the player.
Just use the transform.SetParent(watermillTransform) method on the players transform. Set it to null when he needs to have no parent.