Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by colinmbo · May 07, 2016 at 03:00 AM · rotationmovementvector3controllerangle

Unity 8-Directional Locked Movement (Super Mario 3D World Style)

Hey everyone. I've been struggling for the past few days on something I didn't think would be too difficult but has turned out to be anyway. I know exactly what I want to make and I have a lot of experience in Unity, but I cannot figure out the solution to this problem at all. Here are the details:

  • I am trying to create a top-down character controller where the player can only move in 8 directions using WASD in the input manager to control.

  • The player always faces the direction they are going, like Diablo or Super Mario.

  • However, I still want to lerp, or blend, between the 8 different directions to make everything look smooth.

The main problem I keep having is if I slightly tap a key to move diagonally, the player doesn't complete the rotation towards the diagonal angle and stops between 2 of the 8 directions. Instead of being at a 90 or 45 degrees angle, if you slightly touch the key, the player doesn't finish rotating into that new position and will get stuck in obscure angles like 72 or whatever.

I guess what I am trying to say is I need some sort of way to move the player smoothly in 8 directions, but still is certain to end up on a solid 45, 90, 135, etc. angle. I have tried everything I can think of but I still have no idea how to go about doing this.

TL;DR: Here is a video that shows the game Super Mario 3D World's movement, which is EXACTLY what I'm looking for. Notice how Mario always is locked to facing 8 directions but also smoothly rotates between those directions. Thanks a lot for reading this! I hope someone knows a way to do this.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by colinmbo · May 08, 2016 at 01:02 AM

 Vector3 input = new Vector3 (horizontal, 0f, vertical);
 Vector3 inputRaw = new Vector3 (horizontalRaw, 0f, verticalRaw);
 if (input.sqrMagnitude > 1f)
     input.Normalize ();
 if (inputRaw.sqrMagnitude > 1f)
     inputRaw.Normalize ();
 
 if (inputRaw != Vector3.zero)
     targetRotation = Quaternion.LookRotation (input).eulerAngles;
 
 rigidbod.rotation = Quaternion.Slerp (transform.rotation, Quaternion.Euler (targetRotation.x, Mathf.Round (targetRotation.y / 45) * 45, targetRotation.z), Time.deltaTime * rotationSpeed);
 
 //Movement Code Goes Here...

I had been working on this and it works really well! No problems with it at all whatsoever. It works identical to how it does in Super Mario 3D World. I hope this helps out anyone else trying to achieve this!

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kaitocs · Sep 18, 2016 at 09:58 PM 0
Share

When I paste this the editor tells me that some words (like vertical and horizontalRaw does not exist in the context, how can I do to avoid this? I'm very new to Unity and my c# skills are basically 0, sorry if my question is stupid.

avatar image colinmbo Kaitocs · Sep 18, 2016 at 10:45 PM 1
Share

Those are variables I created myself, so it wouldn't work on your end. Basically, Unity has a built-in "Input $$anonymous$$anager" that takes key presses and lets you access them easily. You can edit the keys from Edit>Project Settings>Input $$anonymous$$anager. For example, I could assign the W and S keys on your keyboard to a variable called "Vertical" and make them interact with each other so that "Vertical" equals 1 when W is pressed and -1 when S is pressed. This makes it very easy to program movement because you can pretty much just say: make the character's Y-axis speed equal to "Vertical". This way the character will move up 1 when you press W and down 1 when you press S, because his Y-position is adding 1 or subtracting 1 every frame. After these variables are assigned in the Input $$anonymous$$anager, you can refer to these variables from your code. This is where you program the movement or whatever you are doing (In this case, rotation). The Input $$anonymous$$anager is just for receiving inputs. So in your code, you can get these values from the Input $$anonymous$$anager by typing: Input.GetAxis("name of the variable here") This is if the value you are trying to grab is an axis, which in this case it is. You don't have to go in and edit anything though if you do not want to-- Unity already has keys in the Input $$anonymous$$anager by default! And my code uses the default axis names so you do not have to change those.

So, that was just exposition because it is really important that you understand why something works and you aren't just blindly copying code. So make sure you read and understand everything above because it makes everything make a lot more sense. But anyways, here's what you have to do:

Replace where it says horizontal with Input.GetAxis("Horizontal")

Replace where it says vertical with Input.GetAxis("Vertical")

Replace where it says horizontalRaw with Input.GetAxisRaw("Horizontal")

Replace where it says verticalRaw with Input.GetAxisRaw("Vertical")

This pretty much gets the inputs from the Input $$anonymous$$anager and puts it in your code in that spot-- meaning if in the Input $$anonymous$$anager, "Horizontal" equals 1, that whole "Input.GetAxis..." equals 1. It is the code interpretation of that Input $$anonymous$$anager axis. You can use this if you want to program movement in your game as well.

Do that word for word and see if that works. I don't use Unity much anymore, but the problem is very basic and that solution should work. I wrote all that stuff at the beginning to make sure that you understood exactly what you were doing. I didn't want to just give you the answer without context, that way you would never learn. Hope this helps man, and remember it's okay that you didn't know what to do, I was in your shoes once too when I started using Unity!

avatar image Kaitocs colinmbo · Sep 19, 2016 at 01:07 AM 0
Share

Thanks a lot for the fast reply, in the meantime I solved my problem, searching in the Unity documentation I found some ways to manage the movement with the Blend Tree in the Animator window, so I added an x and z parameter and I wrote in the script if (input_x == -1) //sx transform.eulerAngles = new Vector3 (0, 270, 0); for the rotation and float input_x = Input.GetAxisRaw ("Horizontal"); float input_z = Input.GetAxisRaw ("Vertical"); for the movement.

Now my character moves 8 ways and also rotate in the right direction thanks to eulerAngles! Usually I don't copy-paste but the guy who write scripts for me wasn't available atm so I was searching for a quick way to go on with my project, but thanks a lot for the kind words, have a nice day!

avatar image andre_95 · Apr 20, 2017 at 03:10 PM 0
Share

Hey, guys! I could use some help! @colinmbo @Bunny83 @$$anonymous$$aitocs

I've put each code to test, but the rotation doesn't work properly. When i type left, my character faces left, like in the Super $$anonymous$$ario video posted here, but while facing that new direction, my character moves towards the camera (that is, sideways). Same happens when pressing right.

Also, when pressing down arrow, he turns until he's looking to the camera and moves to the direction his back is facing.

Same diagonals problem too!

On the console, it says: "Look rotation viewing vector is zero UnityEngine.Quaternion:LookRotation(Vector3)"

I hope what i just wrote seems clear to you! Thanks, in advance, for the help given!

avatar image
0

Answer by Bunny83 · May 07, 2016 at 03:41 AM

Well, it would be interesting how you actually implemented the rotation. If you create a Vector3 out of the two key axis the vector you just have to clamp it to one of those 8 directions.

 Vector3 targetDir;
 
 void Update()
 {
     Vector3 inputDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
     Vector3 v = inputDir.normalized;
     v.x = Mathf.Round(v.x);
     v.z = Mathf.Round(v.z);
     if (v.sqrMagnitude > 0.1f)
         targetDir = v.normalized;
     
     transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetDir), Time.time*5f);
     // your movement code
 }


The trick here is we first normalize the direction so it's length is 1.0. That means the components of "v" are in the range [-1, 1] Simply rounding each component seperately will ensure their values are either -1, 0 or 1. This represents exactly the 8 direction thing you want. If the input vector is too small (i.e. the user doesn't press any keys) we have to prevent that the "targetDir" is set to Vector3.zero, that's why there's the magnitude check

So at any time targetDir represents a vector that always points in one of those 8 directions. Independent from that we do the rotation smoothing each frame in Update.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image colinmbo · May 07, 2016 at 04:32 AM 0
Share

There were a few problems with the code that I went ahead and fixed, but the one problem that is still prevalent is when trying to move the player diagonally. When pressing two keys at the same time to move diagonally, the player moves correctly. However, when you release those two keys, unless the player releases those keys on the same exact frame (which isn't likely), the player turns to the direction of the last pressed key. I was having this same problem last time I attempted this as well. I need to have some sort of buffer time to detect if two buttons are released at the same time. Not sure how to go about doing that. Any suggestions? I'm trying to make it look as much like Super $$anonymous$$ario 3D World as I can, which isn't really turning out so well. Thanks for your help!

avatar image
0

Answer by dKd · Oct 16, 2016 at 04:02 PM

Hello @Colinmbo,

I have the exact same problem : "However, when you release those two keys, unless the player releases those keys on the same exact frame (which isn't likely), the player turns to the direction of the last pressed key".

Have you found a solution for this? I've looked around the forums and anwsers for over 3 hours now. Nothing so far. Doing this in 2D actually.

Thanks in advance.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image colinmbo · Oct 20, 2016 at 09:04 PM 0
Share

I had the same issue too when I was working on this. I've kind of scrapped my own game concept that used this and I haven't used Unity in months, but I still know the solution (sorry for the somewhat late reply by the way). The idea is you want to round the direction of the inputs to the nearest direction (of the 8 directions) and only rotate the player to the new direction once the rounded input equals that direction. Seems kinda confusing, but heres an example: If your input is going from pressing right to pressing right&up (at the same time-- diagonal), there is a transition between those two inputs, so that the value given actually transitions from right to the right&up diagonal. So what you want to do is program it so that the player's rotation is actually the rounded version of that number, so that the player only rotates when the input is mostly facing that direction. Now, I don't have the code anymore, and that sounds complicated, but please read it over and over and try to visualize what I'm saying and you can probably figure out the logic behind it and code it yourself. If you are still confused just tell me and I'll try to come up with a different example for how it all works. The main issue is that the player rotates to the last key press, meaning diagonal movement causes issues unless releasing at the exact same frame. So you will probably want to round those numbers in a way so that you only turn to the new direction when your input is mostly in that direction (So if you tap it there would be no effect). Hope this helps!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

64 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

click to move workig script!! but pls help with rotation!! :( 1 Answer

What is a correct way to move a Drone follow a list of Vector3 points 1 Answer

Place object on radius pointing to a other object 1 Answer

how to convert the angle to roatation? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges