Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 Crono141 · Aug 10, 2014 at 03:54 AM · rigidbody.moveposition

Creating Extending/Retracting Piston. Extends OK, won't retract

I'm trying to create a rigidbody game object of a piston that will extend at a certain speed up to a certain position when the player contacts it, and then retract back to its starting position after the player is no longer contacting it. I created an empty game object, and as children I created a cube (with its colliders turned off so as to not interfere with the cylinder), and then a cylinder. I added a rigid body to the cylinder. Here's my code for the script attached to the cylinder.

 using UnityEngine;
 using System.Collections;
 
 public class Piston : MonoBehaviour {
 
     public float speed;
     private bool pistonExtend;
 
     // Use this for initialization
     void Start () {
         pistonExtend = false;
     }
     
     // Update is called once per frame
     void Update () {
         Debug.Log ("pistonExtend = " + pistonExtend);
         //Debug.Log ("velocity = " + rigidbody.velocity);
         if (pistonExtend == true & transform.position.y < 0.5f) {
             rigidbody.MovePosition(rigidbody.position+Vector3.up * speed * Time.deltaTime);
             //Debug.Break();
         }
         if(pistonExtend == false & transform.position.y > 0.0f)
         {
             Debug.Log("I should be retracting");
             //rigidbody.MovePosition(rigidbody.position+Vector3.down * speed * Time.deltaTime);
             rigidbody.MovePosition(Vector3.zero);
         }
     }
 
     void OnCollisionEnter(Collision other){
         if (other.gameObject.tag == "Player") {
             pistonExtend=true;
             
         }
     }
     void OnCollisionExit(Collision other){
         if (other.gameObject.tag == "Player") {
             pistonExtend=false;
             
         }
     }
 }
 

It works halfway. When the player contacts the cylinder, it extends, but extends past the point where the code was to have it stop extending. And then when it retracts, it snaps back but not to the zero point in the code. It usually snaps back to a point in the y0.5-0.8 range, even though its move position should be to vector3.zero.

When I step through 1 frame at a time after extension, the piston sits at its weirdly offset retracted position steadily. However, if I let it run full speed, it bounces between its offset retracted position and another position lower (but not zero).

As far as I can tell, my code logic should be correct. I've tried many other methods to try and get this to work, but none get as close as this. I've tried update, fixedupdate, and lateupdate. All produce identical behavior. What am I doing wrong?

Comment
Add comment · Show 7
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 robertbu · Aug 10, 2014 at 05:37 AM 0
Share

I tested your code a bit. I added this to the top of the Update() callback:

 if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)) {
      pistonExtend = !pistonExtend;
 }

And I uncommented line 25 and commented out line 26. I placed this script on a cube with a Rigidbody. It worked fine when I hit the space key...both extending and contracting. Next I made the cube kinematic. I then created a "Player" object, and tested the collisions. Again it worked fine. It is only when I turned off 'is$$anonymous$$inematic' that I had issues. So my best guesses:

  • You did not make the object kinematic and therefore the physics between the two objects is playing a role.

  • There is some other script impacting the positioning of your piston.

avatar image Crono141 · Aug 10, 2014 at 02:48 PM 0
Share

It seems there's something wrong with the parent/child relationships going on. Since my cylinder is a child of a placehoder parent object, all transforms should be relative to that parent, correct? This doesn't seem to be the case here. I have the parent object at position y=-0.5, and when I use your debug spacebar to move the cylinder, it moves up twice as far as it should (to world co-ordinates y=0.5, but relative to the parent this is 1.0) and then only retracts back half as far as it should (world co-ordinates 0.0, relative to parent this is 0.5).

Have I messed something up with my parent/child relationship? Is transform.position always relative to world coordinates and not parent co-ordinates? I'll try and make a video of the behavior I'm observing and post the link here.

avatar image robertbu · Aug 10, 2014 at 02:55 PM 0
Share

A transform has ways of reading and setting both the local and the world position. 'transform.position' is the world position of that object, and 'rigidbody.$$anonymous$$ovePosition()' set the world position of that object. If you want to check the local position of the object, you need to use localPosition when reading from the transforms. For example:

  if (pistonExtend == true & transform.localPosition.y < 0.5f) {
avatar image Crono141 · Aug 10, 2014 at 03:11 PM 0
Share

Well, there's my problem. Now my new problem is that the cylinder does not snap exactly back into its original position. Depending on the value of my speed variable, the cylinder can snap as high as 1.5 (relative), and when it snaps back, it can be as low as -0.5. This is a problem because when it snaps too low, the collider is now below where the player is able to touch it, and thus won't be able to actuate the cylinder again. Any way to get it to snap to exactly the positions I need it to?

avatar image robertbu · Aug 10, 2014 at 03:29 PM 0
Share

You did change line 22 to also use transform.localPosition? Beyond that, you should only see a very small amount out of range. For example, given your values of 0.5 for top and 0.0 for bottom, your local position should be between 0.501 and -0.01. That is, your code is not guaranteed to land precisely at .5 or 0.0. First get your local position working correctly so you only have a very slight amount above and below your target values. Then if you need a precise position, use $$anonymous$$athf.Clamp() to restrict the values to the 0.0 to 0.5 range.

Show more comments

1 Reply

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

Answer by Crono141 · Aug 10, 2014 at 05:38 PM

OK. Thanks so much to robertbu for helping me work this out. My final implementation is a little bit different than what I was initially going for. The point of the piston object was to propel the player using physics when the play made contact. This was very difficult to fine tune between bounciness of the player physics material and the rate the piston was extending. I ultimately decided to just have the piston directly change the players velocity instead of using the rigidbody collision to propel the player. Here's the code now.

 using UnityEngine;
 using System.Collections;
 
 public class Piston : MonoBehaviour {
 
     public float speedExtend; // speed piston extends
     public float speedRetract; // speed piston retracts
     public float timeExtended; // time in seconds piston should remain extended before retracting
     public Vector3 jumpspeed = new Vector3 (0, 10, 0); // player's vertical speed when piston is triggered
     private bool pistonExtend; // boolean to tell script to extend piston
     private float timeLeft; // variable to hole amount of time left before piston retracts
     private bool extended; // boolean to denote if piston is in an extended state
     private Quaternion orientation; //get worldspace orientation to make piston object work in any orientation
 
     // Use this for initialization
     void Start () {
         pistonExtend = false; 
         extended = false; //piston starts retracted
         timeLeft = timeExtended; //set time remaining to total time
     }
     
     // Update is called once per frame
     void FixedUpdate () {
         orientation = transform.rotation; //set orientation quat during update so it can move in the world and always work
         if (pistonExtend == true) { //do this when we want to extend
             if(transform.localPosition.y <= 0.5f){ // extend until we reach this position
                 rigidbody.MovePosition(rigidbody.position+orientation*Vector3.up * speedExtend * Time.deltaTime);
                 extended = true;
             }
             timeLeft = timeLeft-Time.deltaTime; // start counting down
             if(timeLeft<0f){
                 pistonExtend=false; //when time runs out, set the retract flag
             }
         }
 
         if(pistonExtend == false & transform.localPosition.y >= 0.1f) //retract back to start position
         {
             rigidbody.MovePosition(rigidbody.position+orientation*Vector3.down * speedRetract * Time.deltaTime);
             timeLeft = timeExtended; //reset extended time
             extended = false;
         }
     }
 
     void OnTriggerEnter(Collider other){
         if (other.gameObject.tag == "Player" && extended == false) {
             pistonExtend=true;
             other.rigidbody.velocity = orientation * jumpspeed; //set player velocity according to orientation
         }
     }    
 }
 

Changing from "update" to "FixedUpdate" solved my weird overtravel issues. Thanks again.

Comment
Add comment · 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

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

2 People are following this question.

avatar image avatar image

Related Questions

Rotate my player around my locked target. 1 Answer

Trouble with implementing Vector2.ClampMagnitude in the Rigidbody2D.MovePosition function 1 Answer

How do I implement both Rigidbody.MovePosition and Rigidbody.MoveRotation simultaneously? 1 Answer

Kinematic "buckets" no longer working in 2018 0 Answers

moveposition() not working when slowing down the game!,rigidbody.moveposition not working when slowing down the game 0 Answers


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