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
1
Question by gioele4 · Dec 01, 2017 at 10:37 AM · physicsmovement scriptrotatearound

How to re-create One More Line mechanic?

Hi, we are developing a multiplayer game based on vehicles that move only forward but when they are near a column they can rotate around it and then exit from the circular movement with a linear and tangent one. The mechanic is really similar to One More Line. Here a graphical scheme to represent the mechanic (in green: collider that detects if the button is pressed) alt text We don't know how to make entry end exit tangent to the collider. We found the function LookAt but we don't know how to use it to make only one axis to point the column, not the entire vehicle's model. In the prototype, we started with a vehicle that is going towards the column as showed in the previous sketch, so for the moment, as you can see in the code, I tried to rotate of 90° (Y axis) the vehicle but doing so it happens that the hook collider and the vehicle's collider doesn't touch anymore, so I was trying to find a solution to make the transition from linear direction to tangent in a smooth way. Here is the code:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class NewBehaviourScript : MonoBehaviour {
 
     private Rigidbody rb; 
     public GameObject hook; //sensor that detects if the vehicle is eligible to rotate
     public bool rotationStarted; //to detect if the vehicle is rotating or not
     public int speed; //speed of vehicle when in linear motion
 
     void Start()
     {
         rb = GetComponent<Rigidbody>();
         rb.AddForce(transform.forward * speed); //adding initial force to Z axis
         rotationStarted = false; //the vehicle does not rotate at the beginning
     }
 
     void OnTriggerStay(Collider other)
     {
             //detect if the vehicle is in the action range of the sensor "hook" and if the player is keeping pressed the button
             if (other.gameObject.CompareTag("hook") && (Input.GetKey(KeyCode.UpArrow)))
             {
             //column = GameObject.FindWithTag("hook"); WARNING: this function doesn't work as expected, because it identifies as object the last one to have the tag "hook", not the true touched object
 
 
             //detect if the vehicle is passing from linear movement to rotation
             if (rotationStarted == false)
                 {
                     rotationStarted = true;
                     //WARNING: the following 4 lines are trying to lerp the rotation but it's infinite, so we must find a way to terminate the rotation
                     var fromAngle = transform.eulerAngles;
                     var targetAngle = transform.eulerAngles + new Vector3(0, -90, 0);
                     transform.eulerAngles = Vector3.Lerp(fromAngle, targetAngle, 0.01f);
                     Debug.Log(transform.eulerAngles + " " + fromAngle + " " + targetAngle);
                 // transform.Rotate(0, -90, 0); //NOT EFFICIENT: if you press the button when it starts to touch the hook, vehicle's collider doesn't touch the hook anymore; I think we should use Lerp
                 //transform.LookAt(column.transform); TEMPORALY DISABLED: we must find a way to LookAt only with an axis, not with the entire vehicle's model
                 }
                 rb.velocity = Vector3.zero; //stopping the linear movement
                 transform.RotateAround(hook.transform.position, Vector3.up, 100 * Time.deltaTime); //rotating around the column
                 Debug.Log("Rotating");
             }
             //detect if the player release the button
             else if (other.gameObject.CompareTag("hook") && Input.GetKeyUp(KeyCode.UpArrow))
             {
                 rotationStarted = false;
                 rb.AddForce(transform.forward * speed); //let the vehicle moves linearly again
                 Debug.Log("Going to be linear");
             }
     }
 
     // DISABLED: it does not works as expected although this --> FOR SECURITY REASONS: in the case the vehicle's collider shouldn't touch the hook anymore while keeping pressed the button, the vehicle stops; this function prevent this bug letting the vehicle going linear
     /*private void OnTriggerExit(Collider other)
     {
         if (other.gameObject.CompareTag("hook"))
         {
             rotationStarted = false;
             rb.AddForce(transform.forward * speed);
             Debug.Log("DOH! Problems with colliders, I'm going to be linear");
         }
         
     }
     */
     void Update()
     {
 
     }
 }

As you can probably note, there are also little problems of other type but for the moment it would be awesome to understand how to rotate the vehicle in order to make it tangent to hook.

Thanks in advance!

gamemechanic.png (167.8 kB)
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

1 Reply

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

Answer by Bunny83 · Dec 01, 2017 at 08:18 PM

Sorry but your 4 images do not represent the mechanics of "One More Line". In that game you will automatically link to the closest point ahead. However you will continue going forward until you you pass the tangent point of the orbit around the link point from your current course. So in the case illustrated in your images you would run straight into the object.


It actually works like this:

TangentialPath


So when you link to an object you will continue to move in a straight line until you reach the tangential point. So the object you are linked to is now exactly 90° to your right or left. At this point you will start moving around the object until you release the button. At this point you will simply move tangentially outward.


So the logic would be more like:

  • Just move forward.

  • If the button is pressed down do a Physics.OverlapSphere to get all link points in range and pick the closest one.

  • Determine if the link point is to the right or left of your current path.

  • Determine if you're before or after the tangent point be calculating the dot product between either your local left or right vector (depends on the condition above) and the vector from your player to the link point. As long as the dot product is > 0 you are before the tangential point and just keep moving.

  • As soon as you are behind or at the tangent point (dot

  • When the button is released you change the movement back to a linear motion.


Once you reach the tangent point you know the radius you have to circle around. I would now calculate the required angular velocity to get the desired tangential velocity. aVel = tVel / radius.

Now you can simply set the velocity of your object to "0,0,0", move the centerOfMass either to the left or right, "radius" units apart so the centerOfMass is at the same point as our link point. When setting the angularVelocity to our calculated value the rigidbody would rotate around the link point.


When you release the button you revert the changes. You would call "ResetCenterOfMass" or set it to (0,0,0) depending on your object, set the angularVelocity to 0 and set the linear velocity back to moving along the local forward axis.


edit The mechanic looks interesting so i quickly implemented it in this script ^^.

 //OneMoreLinePlayer.cs
 using UnityEngine;
 
 public class OneMoreLinePlayer : MonoBehaviour
 {
     public float speed = 3;
     public float searchRadius = 20;
     public float playerSize = 1;
     public LayerMask linkPointLayerMask;
 
     Rigidbody rb;
     LineRenderer lineRenderer;
     Transform linkPoint = null;
     bool circularMotion = false;
     Vector3 angularVel;
 
 
     void Start ()
     {
         rb = GetComponent<Rigidbody>();
         lineRenderer = GetComponent<LineRenderer>();
     }
     
     void Update ()
     {
         if (!circularMotion)
         {
             rb.velocity = transform.forward * speed;
             rb.angularVelocity = Vector3.zero;
         }
         else
         {
             rb.velocity = Vector3.zero;
             rb.angularVelocity = angularVel * speed;
         }
 
         if (Input.GetKeyDown(KeyCode.Space))
         {
             linkPoint = null;
             var colliders = Physics.OverlapSphere(transform.position, searchRadius, linkPointLayerMask);
             float dist = float.PositiveInfinity;
             for(int i = 0; i < colliders.Length; i++)
             {
                 var link = colliders[i].transform;
                 Vector3 dir = link.position - transform.position;
                 float tangentDist = Vector3.ProjectOnPlane(dir, transform.forward).magnitude;
                 if (tangentDist < (link.localScale.x + playerSize))
                     continue; // ignore link points which are in our current path
                 
                 float d = dir.sqrMagnitude;
                 if (Vector3.Dot(dir, transform.forward) < 0)
                     d *= 8; // fake distance of linkpoints behind us to be further away
                             // this prefers link points in front of us.
                 if (d < dist)
                 {
                     linkPoint = link;
                     dist = d;
                 }
             }
         }
         if (linkPoint != null && !circularMotion)
         {
             Vector3 dir = linkPoint.position - transform.position;
             if (Vector3.Dot(dir, transform.forward) <= 0)
             {
                 circularMotion = true;
                 float radius = dir.magnitude;
                 if (Vector3.Dot(dir, transform.right) > 0)
                 {
                     angularVel = transform.up / radius;
                     transform.right = dir;
                 }
                 else
                 {
                     angularVel = -transform.up / radius;
                     transform.right = -dir;
                 }
                 rb.centerOfMass = transform.InverseTransformPoint(linkPoint.position);
             }
         }
 
         if (circularMotion && (!Input.GetKey(KeyCode.Space) || linkPoint == null))
         {
             circularMotion = false;
             rb.ResetCenterOfMass();
             linkPoint = null;
         }
         if (linkPoint != null)
         {
             lineRenderer.enabled = true;
             lineRenderer.SetPosition(0, transform.position);
             lineRenderer.SetPosition(1, linkPoint.position);
         }
         else
         {
             lineRenderer.enabled = false;
         }
     }
 }


Here's how the result looks like:


The link points a just default sphere primitives which have been placed on a special layer, This layer is selected in the "linkPointLayerMask" in the inspector. The player has a rigidbody, this script, a line renderer and a trail renderer. That's all


tangentialpath.png (3.0 kB)
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 Obrebski · May 20, 2018 at 12:20 AM 0
Share

Can you share your repository for this? I tried this code but direction on player exit was different every time...

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

130 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 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 avatar image avatar image

Related Questions

Non slippery movement 1 Answer

Translating Speed into rotation degress\sec 1 Answer

Manual Player Physics Help (C#) 0 Answers

How to rotate around with Rigidbody and respect physics? 0 Answers

need help fixing third person character controller 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