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 Cataclysmix · Oct 01, 2015 at 12:02 PM · c#transformfunctionsparameters

space wrap 3D

Howdy,
I have written this script to wrap objects around in space à la Asteroids, but in 3D.
It works fine (don't have to worry about them wrapping to the exactly correct position, or having to have a duplicate of the object (one wrapping out, one wrapping in) etc, since it's in 3D, and the boundary is invisible in world space).

However, my code definitely doesn't follow the DRY principle. I was wondering if anyone might help me with a function which would replace the repetitions.

it would really just need to take in two parameters. One for in which axis the boundary is being exceeded. And one for whether the boundary is being exceeded in the positive or the negative.

(The Portal() function just marks where the asteroid goes through the 'boundary' with a portal animation (on the gameObject 'wrapWarp'))

 public class PositionWrap : MonoBehaviour
 {
     Vector3 asteroidSize;
     float asteroidDiameter;
     public float boundaryWidth = 100;
     public GameObject wrapWarp;
     public GameObject wrapWarpClone;
 
     void Start()
     {
         asteroidDiameter = transform.localScale.x;
         asteroidSize = transform.localScale;
     }
 
     void Update()
     {
         Vector3 asteroidPos = transform.position;
 
         if (transform.position.x < -boundaryWidth)
         {
             Portal(Vector3.right);
             asteroidPos.x += boundaryWidth * 2 - asteroidDiameter;
         }
         if (transform.position.x > boundaryWidth)
         {
             Portal(Vector3.left);
             asteroidPos.x -= boundaryWidth * 2 - asteroidDiameter;
         }
         if (transform.position.y < -boundaryWidth)
         {
             Portal(Vector3.up);
             asteroidPos.y += boundaryWidth * 2 - asteroidDiameter;
         }
 
         if (transform.position.y > boundaryWidth)
         {
             Portal(Vector3.down);
             asteroidPos.y -= boundaryWidth * 2 - asteroidDiameter;
         }
 
         if (transform.position.z < -boundaryWidth)
         {
             Portal(Vector3.forward);
             asteroidPos.z += boundaryWidth * 2 - asteroidDiameter;
         }
         if (transform.position.z > boundaryWidth)
         {
             Portal(Vector3.back);
             asteroidPos.z -= boundaryWidth * 2 - asteroidDiameter;
         }
 
         transform.position = new Vector3(asteroidPos.x, asteroidPos.y, asteroidPos.z);
     }
 
     void Portal (Vector3 facing)
     {
         wrapWarpClone = (GameObject) Instantiate(wrapWarp, transform.position, Quaternion.LookRotation(facing));
         wrapWarpClone.transform.localScale = asteroidSize;
     }
 }
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
1

Answer by Bunny83 · Oct 03, 2015 at 01:28 PM

I don't see any repetition here except that you should replace "transform.position.XXXX" with "asteroidPos.XXXX". You also might want to put an "else if" for the opposite side since you can't wrap left and right at the same time.

You also could add another member variable to combine "boundaryWidth * 2 - asteroidDiameter" into one value in Start.

You could also use your "direction" vector for the translation

 public class PositionWrap : MonoBehaviour
 {
     Vector3 asteroidSize;
     float asteroidDiameter;
     public float boundaryWidth = 100;
     public GameObject wrapWarp;
     public GameObject wrapWarpClone;
     private float wrapDistance;
     void Start()
     {
         asteroidDiameter = transform.localScale.x;
         asteroidSize = transform.localScale;
         wrapDistance = boundaryWidth * 2f - asteroidDiameter;
     }
 
     void Update()
     {
         Vector3 asteroidPos = transform.position;
 
         if (asteroidPos.x < -boundaryWidth)
         {
             Portal(Vector3.right);
         }
         else if (asteroidPos.x > boundaryWidth)
         {
             Portal(Vector3.left);
         }
         
         if (asteroidPos.y < -boundaryWidth)
         {
             Portal(Vector3.up);
         }
         else if (asteroidPos.y > boundaryWidth)
         {
             Portal(Vector3.down);
         }
 
         if (asteroidPos.z < -boundaryWidth)
         {
             Portal(Vector3.forward);
         }
         else if (asteroidPos.z > boundaryWidth)
         {
             Portal(Vector3.back);
         }
     }
 
     void Portal(Vector3 facing)
     {
         wrapWarpClone = (GameObject) Instantiate(wrapWarp, transform.position, Quaternion.LookRotation(facing));
         wrapWarpClone.transform.localScale = asteroidSize;
         transform.position += facing * wrapDistance;
         // maybe create another "portal" on the "exit"?
     }

I would probably rename the "Portal" method to "Wrap" or something like that.

ps: I think i will never understand why people do things like:

 transform.position = new Vector3(asteroidPos.x, asteroidPos.y, asteroidPos.z);

asteroidPos is already a Vector3. A Vector3 is a value type so each time you pass it around you already work with a copy.

Comment
Add comment · Show 2 · 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 Bunny83 · Oct 03, 2015 at 01:45 PM 0
Share

While it is possible to "combine" those 6 cases into a for loop i really really don't recommend something like that as it's less efficient and cryptic.

 void Update()
 {
     Vector3 asteroidPos = transform.position;
     for(int i = 0; i < 6; i++)
     {
         Vector3 dir = Vector3.zero;
         float sign = (i<3)?1f:-1f
         dir[i%3] = -sign;
         if (sign*asteroidPos[i%3] > boundaryWidth)
         {
             Portal(dir);
         }
     }
 }

This should be seen as "anti sample" because even the code is way shorter it's way less efficient. Also this only works when your game area is a cube. For a box (with different dimensions) it's getting more complicated.

The indexer of Vector3 might get handy in some cases, but it's less efficient compared to accessing the components directly. That indexer just has a switch case and does access each component based on the given index. That's unnecessary overhead. But performance isn't the main issue. Code should be easy to understand. This hacky for loop solution is hard to read and hard to understand.

You really should stick with each case seperately.

edit
Had an error in my logic ^^ You can't use $$anonymous$$athf.Abs. I fixed it (i guess ^^).

avatar image Cataclysmix · Oct 03, 2015 at 08:00 PM 0
Share

Thanks for your help.
I guess because the way I wrote the script, when I first replaced "transform.position.XXXX with asteroidPos.XXXX in the if condition it didn't work.. I thought it needed a Vector3 for where it went "in" to the "boundary" and another separate one for where it came "out".

I thought I might be able to use the "direction" vector for the portal in the translation, and put the translation into the function.. thanks heaps.

I have, since posting the question, created another portal on the "exit" (basically a reverse animation of the portal on the "entry")

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Distribute terrain in zones 3 Answers

Multiple Cars not working 1 Answer

Optional parameter, editor raises error "Unexpected symbol `=' " 0 Answers

Why is transform.LookAt backwards for my model? 2 Answers

"Lerp" back to original position after animation. 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