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 /
  • Help Room /
avatar image
1
Question by OctoMan · Oct 20, 2015 at 09:45 PM · rotationlerpmouseclickslerp

How to move Tile Up, Rotate by 90 degrees, then down again on click, while supporting dragging tile freely

Hi,

i word on a puzzlegame where i want the player to drag around tiles and when the player just pressed the left mouse button, i want the tile to move up a bit, then rotate by 90 degrees on the y-axis and the put it back down.

This should happen when i use a raycast and click the left mousebutton.

i just started with that:

 void Update()
 {
     if (Input.GetMouseButtonDown (0)) 
     {
         ray = Camera.main.ScreenPointToRay (Input.mousePosition);
         {
         if (Physics.Raycast (ray, out hit)) 
             {
             if (hit.transform.tag == "card") 
                 {
                     print (hit.collider.name);
                     
                     
                     oldRotation = hit.transform.rotation;

                     Vector3 newRotationAngles = oldRotation.eulerAngles;
                     newRotationAngles.y += 90;
                     newRotation = Quaternion.Euler (newRotationAngles);

                     isRotating = true;
                 }
             }
         
         }
     }
     if(isRotating)
     {
         hit.transform.rotation = Quaternion.Slerp(oldRotation,newRotation,Time.deltaTime * speed);
     }
 }

The problem is the rotation wont work, and i have no idea how to move the tile up before, and move it down after.

Thanks in advance.

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

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by MrMeows · Oct 22, 2015 at 08:02 AM

Replace "Quaternion.Slerp(oldRotation" with "Quaternion.RotateTowards(hit.transform.rotation". Slerp uses a float between 0 and 1 as its third input. RotateTowards uses an angle as its third input. Also, you should change the rotation from the current rotation instead of the old one. Otherwise, you never make any progress. As for moving the tile...

if(isRotating)
{
if(hit.transform.position.y < maximumHeight)
{
if(Quaternion.Angle(hit.transform.rotation,newRotation) >= 1)
{
transform.Translate(0,Time.deltaTime * liftSpeed,0);
} else
{
if(hit.transform.position.y > minimumHeight)
{
transform.Translate(0,Time.deltaTime * -liftSpeed,0);
}
}
} else
{
if(Quaternion.Angle(hit.transform.rotation,newRotation) >= 1)
{
hit.transform.rotation = Quaternion.RotateTowards(hit.transform.rotation,newRotation,Time.deltaTime * speed);
} else
{
transform.Translate(0,Time.deltaTime * -liftSpeed,0);
}
}
}
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 OctoMan · Oct 24, 2015 at 10:40 AM 0
Share

Hi, sorry for my late reply. I was trying alot around. Well my oldPosition is basicly the currentposition. I have the rotatation working as @Statement showed me. Currently i try to get mouseclick and mousedrag under one hat.

$$anonymous$$y dragging works so far, but also the mouseclick gets attention, any idea how to handle both seperatly?

avatar image Statement OctoMan · Oct 24, 2015 at 10:45 AM 0
Share

Did you look at my updated example and played the demo? It does dragging (well, swapping) and rotation.

avatar image OctoMan Statement · Oct 24, 2015 at 10:49 AM 0
Share

Hi, yes i looked into it, well it's not what i am exaclty trying to achieve. I want the tile stick on the mouse and drag it freely around for response to the player. Thats why i tried to figure the the difference between dragging and clicking an other way.

Show more comments
avatar image
0

Answer by Statement · Oct 21, 2015 at 06:48 AM

One way to make code run in sequence over several frames is to use coroutines with StartCoroutine.

  // A *high level* example of how to use Flip
 void Update() {
     if (IWasClicked)
         StartCoroutine("Flip"); // Coroutine Flip for moving up, rotate, down
 }

 bool isRunning;
 // A *high level* example of how your code could be structured
 IEnumerator Flip() {
     if (!isRunning) {
         isRunning = true;
         yield return StartCoroutine("Step_MoveUp"); // Coroutine Step_MoveUp for moving up
         yield return StartCoroutine("Step_Rotate90"); // Coroutine Step_Rotate90 for rotation
         yield return StartCoroutine("Step_MoveDown");  // Coroutine Step_MoveDown for moving down
         isRunning = false;
     }
 }

You could also make a state machine. There are a few ways you can go about. For instance you could just have a int to define which state you are in (0 = waiting for input, 1 = moving up, 2 = rotating, 3 = moving down) and switch (state). A slight improvement on readability and safety would be to declare an enum with the four states but it would work the same as having an int. An object oriented approach would solve it with polymorphism where you subclass (or "extend") a state type (see state pattern). You could also create components that deal with one problem each and let your existing component manage those other components.

I made an example project you can checkout.

  • Project

  • FlipOnClick.cs

  • BoxInputManager.cs

Interactive demo (Updated)

Interactive demo (Old)

If we look at the core of the Flip coroutine, it looks like this:

         Vector3 rest = transform.position;
         Vector3 lift = transform.position + Vector3.up;
         Quaternion right = transform.rotation * Quaternion.Euler(0, 90, 0);

         while (MoveTowards(lift)) { yield return null; }
         while (RotateTowards(right)) { yield return null; }
         while (MoveTowards(rest)) { yield return null; }

Basically it is looping until MoveTowards return false, then does the same for RotateTowards and finally with MoveTowards again. yield return null;with coroutines means "pause execution until the next frame".

Looking at MoveTowards, it is very simple but the syntax can look a little odd at first glance.

     private bool MoveTowards(Vector3 toward)
     {
         return toward != (transform.position = Vector3.MoveTowards(
             transform.position, toward, moveSpeed * Time.deltaTime));
     }

This is a oneliner which updates transform.postion and then compares it with toward. Since it is designed to be used in the while loop, it return true if transform.position hasn't reached toward. So the while loop will run until transform.position reach toward.

RotateTowards is pretty much the same, except using transform.rotation.

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 OctoMan · Oct 22, 2015 at 10:53 AM 1
Share

First of all i want to say, thats an amazing and well written explaination for that, also it works like a charm. I really need to learn alot more. I will study all and also will try to do it as you mentioned with an enum/int counting around.

I later on also want to take those tiles and drag them around the playfield and switch those with other tiles. Which also mean if i drag them they need to go up hold and go down on release. $$anonymous$$ay i need to use a statemachine for that?

avatar image Statement OctoMan · Oct 22, 2015 at 12:38 PM 0
Share

You don't necessarily need to create a statemachine for it. To me it sounds like you should break up the problem into two separate ones. One to deal with input handling (dragging replaces tiles, clicking rotates tiles) and one to deal with the event handling of said actions.

Anyway, once you have decided on an implementation to detect if the user clicks, begin drag and release drag, all you have to do is either call Flip or Swap. Just add input guards to not perform any input actions in case a coroutine is running (so you don't get a flip and a swap at the same time).

I updated the github repository so you can view the changes there.

avatar image OctoMan Statement · Oct 23, 2015 at 08:17 AM 0
Share

I have heard of the new event system, i just thought there is an easier way understandable for me. I just have basic knowledge of program$$anonymous$$g, so it is not easy stuff at all. I just made dragging with normal scripting but it seems it wont work with your flipping around stuff.

I will look into the event system, not sure how to construct this, with snapping, since my current dragging works good so far, sadly without the move up/down animations at the moment.

Thanks for the github stuff, i'll again look into it.

 public class DragingTiles : $$anonymous$$onoBehaviour {
 
     private Vector3 screenPoint;
     private Vector3 offset;
     public Vector2 ylimits = new Vector2(-9, 9);
     public Vector2 xlimits = new Vector2(-9, 9);
 
     public Vector3 oldPosition, newPosition;
 
     public Layer$$anonymous$$ask Playfield;
 
     public bool isdragged = false;
 
     // Use this for initialization
     void Start () {
     
     }
     
     // Update is called once per frame
     void Update () 
     {
         //snap to others
         if(isdragged)
         {
             Ray ray = new Ray (transform.position, Vector3.down);
             RaycastHit hit; //save the hitted unit
             
             Debug.DrawRay(ray.origin, ray.direction, Color.red);
             if(Physics.Raycast(ray, out hit, 6, Playfield))
             {
                 if(hit.collider.tag == "SnapField")
                 {
                     newPosition = hit.collider.gameObject.transform.position;
                 }
                 else
                 {
                     newPosition = oldPosition;
                 }
             }
         }
     }
 
     void On$$anonymous$$ouseDown()
     {
         screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
         offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
         oldPosition = transform.position;
     }
     
     void On$$anonymous$$ouseDrag()
     {
         Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
         Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + new Vector3(0,1,0);
         //curPosition.y = $$anonymous$$athf.Clamp(curPosition.y, ylimits.x, ylimits.y);
         //curPosition.x = $$anonymous$$athf.Clamp(curPosition.x, xlimits.x, xlimits.y);
         
         isdragged = true;
         
         transform.position = curPosition;
         
     }
     
     void On$$anonymous$$ouseUp()
     {
         isdragged = false;
         transform.position = newPosition;
     }
 }

I believe the problem is the direct mouseinputs to consider what is flipping, what is dragging.

Show more comments

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

35 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

Related Questions

Rotate on Transform.localeulerAngels smoothly 0 Answers

Lerp going crazy when negative 1 Answer

Rotation (Quaternion.Lerp) not working 0 Answers

Slerp rotation issue when calling a lot 0 Answers

How to control rocket pathing with Quaternion.Slerp 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