Trying to fix the scale of a game object in Unity 2D - unity3d

I have a script that faces my player (cube) to its moving direction. It also has a grappling gun, but when he turns to its moving direction, gun turns too and it can't use grappling gun when i try to grapple and object staying on the opposite site of my player.
This is how i turn my player:
private void Flip()
{
if (isFacingRight && HorizontalInput() < 0f || !isFacingRight && HorizontalInput() > 0f)
{
Vector3 localScale = transform.localScale;
isFacingRight = !isFacingRight;
localScale.x *= -1f;
transform.localScale = localScale;
}
}
If I can fix the localScale of my gun, so that it won't multiplied with -1 when i multiply the whole body.
Any idea? Thanks a lot.

As I understand the question: you want to flip the player but not flip the gun (which is a child of the player).
One way of doing this is to organize the Player object like this:
-Player (prefeb, invisible)
--PlayerGraphicChild (Cube, flip this one only)
--PlayerGunChild (don't flip this one).
Another way is to add a new prefeb called Gun, and set the position of that object to one of the children of Player. Organize the hierarchy like this:
-Player (flip this one)
--PlayerGunDolly (flips with parent)
and create a new prefeb:
-Gun (has a component that sets the transform.position to transform of PlayerGunDolly. Does not flip.)

Related

Unity / Mirror - Is there a way to keep my camera independent from the player object's prefab after start?

I'm currently trying to create a multiplayer game using mirror!
So far I've been successful in creating a lobby and set up a simple character model with a player locomotion script I've taken and learnt inside out from Sebastian Graves on YouTube (you may know him as the dark souls III tutorial guy)
This player locomotion script uses unity's package 'Input System' and is also dependent on using the camera's .forward and .right directions to determine where the player moves and rotates instead of using forces on the rigidbody. This means you actually need the camera free in the scene and unparented from the player.
Here is my HandleRotation() function for rotating my character (not the camera's rotation function):
private void HandleRotation()
{
// target direction is the way we want our player to rotate and move // setting it to 0
Vector3 targetDirection = Vector3.zero;
targetDirection = cameraManager.cameraTransform.forward * inputHandler.verticalInput;
targetDirection += cameraManager.cameraTransform.right * inputHandler.horizontalInput;
targetDirection.Normalize();
targetDirection.y = 0;
if (targetDirection == Vector3.zero)
{
// keep our rotation facing the way we stopped
targetDirection = transform.forward;
}
// Quaternion's are used to calculate rotations
// Look towards our target direction
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
// Slerp = rotation between current rotation and target rotation by the speed you want to rotate * constant time regardless of framerates
Quaternion playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
transform.rotation = playerRotation;
}
It's also worth mentioning I'm not using cinemachine however I'm open to learning cinemachine as it may be beneficial in the future.
However, from what I've learnt and managed to find about mirror is that you have to parent the Main Camera under your player object's prefab so that when multiple people load in, multiple camera's are created. This has to happen on a Start() function or similar like OnStartLocalPlayer().
public override void OnStartLocalPlayer()
{
if (mainCam != null)
{
// configure and make camera a child of player
mainCam.orthographic = false;
mainCam.transform.SetParent(cameraPivotTransform);
mainCam.transform.localPosition = new Vector3(0f, 0f, -3f);
mainCam.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
cameraTransform = GetComponentInChildren<Camera>().transform;
defaultPosition = cameraTransform.localPosition.z;
}
}
But of course, that means that the camera is no longer independent to the player and so what ends up happening is the camera rotates when the player rotates.
E.g. if I'm in game and looking to the right of my player model and then press 'w' to walk in the direction the camera is facing, my camera will spin with the player keeping the same rotation while my player spins in order to try and walk in the direction the camera is facing.
What my question here would be: Is there a way to create a system using mirror that doesn't require the camera to be parented to the player object prefab on start, and INSTEAD works by keeping it independent in the scene?
(I understand that using forces on a rigidbody is another method of creating a player locomotion script however I would like to avoid that if possible)
If anybody can help that would be greatly appreciated, Thank You! =]
With the constraint of your camera being attached to the player you will have to adapt the camera logic. What you can do is instantiate a proxy transform for the camera and copy that transforms properties to your camera, globally, every frame. The parent constraint component might do this for you. Then do all your transformations on that proxy.
Camera script with instantiation:
Transform proxy;
void Start(){
proxy = (new GameObject()).transform;
}
void Update(){
//transformations on proxy
transform.position = proxy.position;
transform.rotation = proxy.rotation;
}

Detect collisions between 2 objects

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

How to lock the Y-axis for unity's Cinemachine?

I have a ball which we can throw here and there in my game. I want my cinemachine vcam to move only in the x direction with the ball. And just look up to the ball while its in air. I don't want the camera to move in y direction along it too.
I have set the look at and follow fields to the ball only. All i want it the camera to not follow the ball in y. (Basically, follow the ball in x, and keep looking at it in the air)
How can I achieve this is the most trivial and beautiful way possible? (open to scripts, but the lesser code the better)
as i've just tested, You can write a script that attaches to your camera, where you create a new vector3 with the x of your ball, and the frozen Y values that you want here's an exemple:
public class CameraController : MonoBehaviour
{
//Assign your ball in the inspector
public Transform target;
// Update is called once per frame
void Update()
{
//Here i assumed that you want to change the X
Vector3 newCamPosition = new Vector3(target.position.x, yourValue, yourValue);
gameObject.transform.position = newCamPosition;
}
}
Hope It helped <3

Grip Between Two Objects

I need grip between two objects actually small cube is a player having rigid body and big cube is an object that helps small cube to jump on it and keep jumping on other big cubes to reach to the destination. I need when the player jumps and land on rotating cube so there should friction between them by default the player should rotate with big cube cause its on the big cube.
The expected result was that the small cube having rigid body should also rotate with big cube cause big cube is rotating and is on the big cube:
You can set the small cube gameobject as child of the big cube gameobject. This should to the trick.
----EDIT AFTER COMMENTS
If you need to change the child hiearchy (because the small cube can move away), then you need a script that add and remove the child when required.
=> When player (small cube) is on the big cube you much child player to the big cube.
=> When player (small cube) moves away of the big cube you much de-child player to the big cube.
If you're using rigidbodies you may use OnCollisionEnter and OnCollisionExit.
You may attach this monobehaviour to the big cube.
public class BigCubeScript : MonoBehaviour
{
private void OnCollisionEnter(Collision other)
{
//check if the colliding object is player (here I'm using a tag, but you may check it as you prefer)
if (other.gameObject.tag == "Player")
//change the parent of the player, setting it as this cube
other.transform.SetParent(this.transform);
}
void OnCollisionExit(Collision other)
{
if (other.gameObject.tag == "Player")
//remove the player from the cube
other.transform.SetParent(null);
}
}
You can also apply a force to the rotation of the player until he stays on the cube. In this case it's quite important to balance the rotation force well (you can try it in the editor).
public class BigCubeScript : MonoBehaviour
{
//you may change this to add or remove the force
Vector3 _rotationForce = new Vector3(0, 5, 0);
private void OnCollisionStay(Collision other)
{
var rigidbody = other.gameObject.GetComponent<Rigidbody>();
Quaternion deltaRotation = Quaternion.Euler(_rotationForce * Time.deltaTime);
rigidbody.MoveRotation(rigidbody.rotation * deltaRotation);
}
}
Further info in OnCollisioEnter and OnCollisionExit in this Unity Tutorial
Further info on the Tags in this Unity Tutorial
You could try to constrain position and rotation on Rigidbody of the small cube. After that you could call constrains.none so that you could allow jump again and do that every time the small cube collides with the big one. Hope it helps :)

While a gameobject turn, when i put an object top of that. that object does not rotate like it should, how to fix this?

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.