I'm really new to using unity and C# so excuse me if this is a dumb question but I really haven't been able to figure it out..
I just want to flip my sprite in my 2D game but when I do that using localScale the location of the sprite changes too.
It's like this:
flipped right:
| [sprite facing right]
flipped left:
[sprite facing left] |
the "|" sign stays in one location in the game. Wow this is so hard to describe without pictures but I hope you can understand me. I can't post images because I'm new to the forum.
So the issue is:
When I change the localScale the whole sprite moves and I don't understand why.
Could someone please help me? Thanks in advance!
My code:
private void HandleInput()
{
if (Input.GetKey(KeyCode.D))
{
_normalizedHorizontalSpeed = 1;
if (!_isFacingRight)
Flip();
}
else if (Input.GetKey(KeyCode.A))
{
_normalizedHorizontalSpeed = -1;
if (_isFacingRight)
Flip();
}
else
{
_normalizedHorizontalSpeed = 0;
}
if(_controller.CanJump && Input.GetKeyDown(KeyCode.Space))
{
_controller.Jump();
}
}
private void Flip()
{
transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
_isFacingRight = transform.localScale.x > 0;
}
}
Make sure the origin of your sprite is configured correctly. In most cases, the origin of the sprite should be in the very middle, which would make a negative transform flip it around the center. If however the origin is in a corner, that position stays the same at any scale, meaning it'll be in the same place and your sprite will appear to move when flipping. This can also happen if your sprite only occupies a portion of the image used for the sprite - it's not actually moving, but since you can't see the rest of the image, it appears to be.
Related
So, Hey guys. Im new to Unity and Im trying a very simple code that allows the player to Zoom-in & Zoom-Out. Here's the code of it:
[Header("Vertical Zooming")]
[SerializeField] private float zoomSpeed;
private void Update()
{
VerticalZooming();
}
private void VerticalZooming()
{
Vector3 initialPosition = new Vector3();
// bool canMove = false;
if (Input.GetMouseButtonDown(0))
{
initialPosition = mCamRef.ScreenToViewportPoint(Input.mousePosition);
Debug.Log(initialPosition.y);
}
if (Input.GetMouseButton(0))
{
Vector3 newPosition = mCamRef.ScreenToViewportPoint(Input.mousePosition);
Debug.Log("newPosition" + newPosition.y);
if (newPosition.y < initialPosition.y)
{
Zoom((zoomSpeed * Time.deltaTime) * -1f);
}
if (newPosition.y > initialPosition.y)
{
Zoom(zoomSpeed * Time.deltaTime);
}
intialPosition = newPosition;
}
}
private void Zoom(float inZoomSpeed)
{
transform.Translate(mCamRef.transform.position.z * inZoomSpeed * transform.forward);
}
So, if you see the code above. On mousebuttondown we note down the initial position and on holding the mouse button we keep track of new position constantly.. What i want is pretty simple. With reference to my initial mouse click im checking if my new position is greater in y is yes i need to zoom out. If new position is lower than initial position in y-axis. Them, i need to zoom in. Which I did, But for some reason its not working.
Two problems here:
Though if there is no change to newposition i.e., even if both my newposition variable and initial position variable are in same spot my camera moves(Zoom-out in my case) which shouldn't happen. It should only happen if my newPosition.y variable is greater that that of initialposition.y. I'm not able to figure out why this is happening. I tried using bool conditions to do this, but failed.
If i play test this in my mobile.. Its only going on one direction. in my case its only zooming out continously though my zoom-in if-condition meets. But when playtesting in unity game window. The zoom in works when my mouse is out of the game-screen. Because its only working outside the game screen.This is the reason its not working in mobile as there is no space outside mobile display. Which i dont know why this is happening or dont know how to overcome this.
Let me know why! Im stuck at it for a long time and not getting any idea. Thanks <3
If Any doubt in question let me know. Sorry for a huge explanation. Just wanted to be very precise on the question.
I have seen people suggesting zoom in zoom out through using FOV. But i wanna do it using translate or move the camera itself.
So your problem here is on taking count on the screenToViewPort point.
Instead just try this..
if (Input.GetMouseButtonDown(0))
{
mInitialPosition = Input.mousePosition.y;
}
if (Input.GetMouseButton(0))
{
mChangedPosition = Input.mousePosition.y;
if (mChangedPosition == mInitialPosition)
{
return;
}
if (mChangedPosition < mInitialPosition)
{
Zoom((mZoomSpeed * -1f) * Time.deltaTime);
}
if (mChangedPosition > mInitialPosition)
{
Zoom(mZoomSpeed * Time.deltaTime);
}
}
private void Zoom(float inZoomSpeed)
{
transform.Translate(mCamRef.transform.position.z * inZoomSpeed * transform.forward);
}
Not sure how ScreenToViewport point works... But I guess this code should do the magic for you... Here I'm just straight away taking the mouse.y value on click and hold and did the same functions as you did and also telling it not to do anything when both the y values are same and return the function... So meaning that you already had everything in your code itself... Have a nice day
So I'm testing around with Unity and Visual Studio, and as a starter project I'm working to replicate Zelda (NES) and I'm starting with movement.
So far, with much jank, I've figured out how to prevent diagonal movement, but I'm having trouble figuring out the next part. In the game, if favors vertical movement when there are 2 inputs, but if you hit a wall, it lets you move horizontally until nothing is blocking your vertical movement.
I do not know enough to even think about how to do this. Anyone have an idea that can set me the right direction? Or perhaps just a better way of doing it? I'm still learning C#
public float MoveSpeed;
public Rigidbody2D rb;
Vector2 movement;
void Update() {
MovementInput();
}
private void FixedUpdate() {
rb.velocity = movement * MoveSpeed;
}
void MovementInput() {
float mx = Input.GetAxisRaw("Horizontal");
float my = Input.GetAxisRaw("Vertical");
//This makes diagonal impossible, favoring vertical.
if (my != 0) {
mx = 0;
}
movement = new Vector2(mx, my).normalized;
}
Try to compare the horizontal and the vertical axis absolute value. The highest would gives you the good direction.
if (Math.Abs(my) > Math.Abs(mx)) {
// up or down
} else {
// left or right
}
I have written this code for my controller in Unity. The problem is that the jump in Y axis has different height than the jump for X and Y axis simultaneously.
// Update is called once per frame
void FixedUpdate()
{
Debug.Log(rigidbody.velocity);
float inputX = Input.GetAxis("Horizontal");
//Movement X
if(inputX != 0 && isGrounded)
{
animator.SetBool("isWalking", true);
rigidbody.velocity = new Vector2(inputX*speed, 0);
//Turn left & right
if(inputX > 0)
{
spriteRenderer.flipX = false;
} else if (inputX < 0)
{
spriteRenderer.flipX = true;
}
} else
{
animator.SetBool("isWalking", false);
}
//Jump
if(Input.GetAxis("Jump") > 0 && isGrounded)
{
rigidbody.AddForce(Vector2.up * jumpImpulse, ForceMode2D.Impulse);
}
}
if i understand your code right, you only gives force to X when you are in ground, so i suggest to remove isgrounded variable and use it just for jump for example in your update method
if(isGround){
if(keypress == y){
addforce in Y
}
}
actually im a bit oxided in unity but i hope to be usefull about logical
I am pretty bad myself when it comes to the jumping physics, but i found these links maybe these will help you.
Unity 2d jumping script
https://answers.unity.com/questions/710765/2d-c-jump-script-addforce-1.html
I also want to know which jump is higher. You stated that there is a height difference when you jump without moving vs when you are moving. Which of the two jumps higher? Are you actually sure that one jumps higher than the other or does it just look like one jumps higher? You can test this by placing a platform an test if you can make it.
Sorry I can't me of more help and can only speculate of what might cause the problem. I would recommend however that when you do movement that you multiply it by Time.DeltaTime. This makes the movement time based instead of frame based. This will make the movement feel smoother.
I'm learning unity and c#, and want to make my movement to be camera relative movement instead of world relative movement. How do I do that?
I'm learning unity and c#, my unity version is 2018.3.12f1. I would be happy for help.
just to let know, instead of moving the cam I'm rotating the player.
void Update()
{
float AxisY = Player.transform.eulerAngles.y;
/* Movement starts here */
Vector3 Movement = new Vector3 (Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) { //running code
Player.transform.position += Movement * running_speed * Time.deltaTime;
} else {
Player.transform.position += Movement * speed * Time.deltaTime;
}
/*Movement ends here */
/* Rotation controller starts here */
Quaternion target = Quaternion.Euler(Player.transform.eulerAngles.x, Player.transform.eulerAngles.y, Player.transform.eulerAngles.z);
/*if (Player.transform.eulerAngles.x != 0 || Player.transform.eulerAngles.z != 0 || Player.transform.eulerAngles.y != 0) {
Player.transform.rotation = Quaternion.Euler(0,0,0);
}*/
if (Input.GetKey(KeyCode.E))
{
Debug.Log("E got pressed");
//float AxisYPositive = Player.transform.eulerAngles.y;
AxisY = AxisY+1;
Player.transform.rotation = Quaternion.Euler(0, AxisY, 0);
} else if (Input.GetKey(KeyCode.Q))
{
Debug.Log("Q got pressed");
//float AxisYNegetive = Player.transform.eulerAngles.y;
AxisY=AxisY-1;
Player.transform.rotation = Quaternion.Euler(0, AxisY, 0);
}
}
}
The player's movement is world relative, how to make the movement camera relative?
If you want to make the movements relative to the gameObject, call the method Transform.Rotate() on the transform of the gameObject you want to rotate rather than modifying its Quaternion directly. Just make sure the final argument is set to Space.Self.
if (Input.GetKey(KeyCode.E))
{
Debug.Log("E got pressed");
//float AxisYPositive = Player.transform.eulerAngles.y;
AxisY = AxisY+1;
Player.transform.Rotate(Quaternion.Euler(0, AxisY, 0), Space.Self);
}
In general you don't want to directly mess with objects transform.rotation, at least not unless you at least somewhat understand quaternions (I don't!).
I can see a few issues with your code, but the common thread seems to be that you don't really understand how transforms work. Specifically, you might want to look into World/Local space.
The usual way to control a player goes roughly like this:
void DoMovement(Transform player)
{
//If you move first your controls might feel 'drifty', especially at low FPS.
Turn(player);
Move(player);
}
void Turn(Transform player)
{
float yaw = Input.GetAxis("Yaw") * time.deltaTime; //Aka turn left/right
player.Rotate(0, yaw, 0, Space.Self);
// Space.Self is the default value, but I put it here for clarity.
//That means the player will rotate relative to themselves,
//...instead of relative to the world-axis, like in your code.
}
You didn't ask about movement, but as-is your character will always move relative to the world. The below should make it move relative to the camera.
Transform _cameraTransform; //Assumes this is set druing Start()
void Move(Transform player)
{
var forwardMove = _cameraTransform.Forward; //Get whatever direction is 'forward' for camera
forwardMove.Y = 0; //Don't want movement up and down.
forwardMove = forwardMove.normalized; //Normalize sets the 'power' of the vector to 1.
//If you set Y to 0 and don't normalize you'll go slower when camera looks down
//...than when camera is flat along the plane
player.position += forwardMove * Input.GetAxis("Vertical") * time.deltaTime;
//Here you could do the same for strafe/side to side movement.
//Would be same as above, but using the transform.right and Horizontal axis
}
Now, I'm making some assumptions here since you haven't specified what kind of game it is and what kind of controls you want. I'm assuming you have a character running around on a mostly flat plane (no aircraft/spaceship controls), and that the camera is attached to the player. This might not not actually be the case.
In any case I advice you to check out the tutorials, especially the Roll-a-Ball tutorial which I have found is good for beginners to get a grasp on basic players controls that are not just world-relative. The other tutorials, too, are pretty good if you think they're interesting.
Aside from the official Unity tuts a ton of decent to amazing tutorials out there, including video tutorials, so for something like this you could just search for <game type> tutorial and pick whatever seems good to you. While getting started I advice you to avoid the shortest videos, as you will likely benefit greatly from explanation that only fits in longer videos. Of course, that doesn't mean you should pick the longest videos either.
In case someone needs to move an object and don't care about colliders, you can use transform.Translate and assign to his second parameter relativeTo your camera (or any transform) to automatically calculate the translation relative to the object assigned.
I'd like to thank you in advance for helping me with this issue.
I have a player that consists of three part:
The body
The head
and the Arm
All three of these are individual sprites.
I have grouped them all under one Empty GameObject that I named "Player"
I have then added an animation on the "Player" GameObject that changes the Y position from 0 to 0.022, and then from 0.022 back to 0.
This create a nice little hover animation where the character bounces up and down.
The animation works perfectly fine!
However, I also have a script attached to the "Player" object, this script is called "PlayerController".
In PlayerController I change the player's x Position if they hold down A (for leftwards movement) or D (for rightwards movement).
protected bool facingRight = true;
float xPos = 0;
void Update()
{
if (Input.GetKey(KeyCode.D))
{
xPos += 0.01f;
if (!facingRight)
{
Flip();
}
}
else if (Input.GetKey(KeyCode.A))
{
xPos -= 0.01f;
if (facingRight)
{
Flip();
}
}
gameObject.transform.position = new Vector2(xPos, transform.position.y);
}
protected void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
When I hold A or D, the character refuses to move. However he does flip correctly.
I personally think my animation is fighting the script, and that the animation has a higher priority than the script...?
Here's a video of me explaining my issue
(Not sure if videos are generally accepted in this community or not. If not, then I apologize)
If you guys could please help me understand what is happening and how to correct it I would be extremely grateful.
Thank you! :)
Solved the problem after hours of tinkering.
Turns out the solution was simple:
All I had to do was structure my player like this:
Player (Empty GameObject)
PlayerAssembly (Body, Head, and Arm's parent)
Body Parts (Body, Head, Arm)
and then put the script, rigidBody2D, and collider on "Player".
Then put the animator on "PlayerAssembly".