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 Skyfall106_Gaming · Mar 18, 2017 at 10:07 AM · c#unity 5building

Making Building Placement Buildings rotateable

Hey! So I have this script where you can place buildings and stuff but im not sure how to make it so when your trying to place it you can rotate it on a 90-degree scale so from 90 to 180 to 270 to 360. How can I do this? Here is my code: PS This is my BuildingManager script. If you need my BuildingList, BuildingColision or even the ButtonGUI just tell me :)

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 /// <summary>
 /// Build manager.
 /// 
 /// This Script is attached to a empty GameObject
 /// </summary>
 
 [System.Serializable]
 public class Snapping
 {
     public bool snappingEnabled = true;
     public float snapRadius = 2.0f;
     public float snapMagin = 0.0f;
     public SnapSides snapSides;
 }
 
 [System.Serializable]
 public struct SnapSides
 {
     // based on objects facing direction
     public bool left, right, top, bottom, front, back;
 }
 
 public class BuildManager: MonoBehaviour 
 {
     public int SelectedBuilding;
     private int LastSelectedBuilding;
     public GameObject[] Building;
     
     public List<BuildingList> buildings = new List<BuildingList>();
     
     public string TerrainCollisionTag;
 
     private bool ghostOn = false;
     private GameObject ghost;
     private BuildingCollision ghostCollision;
 
     private bool isFlat;
     public float maxSlopeHigh = 5f;
 
     public bool isBuildingEnabled { get; private set; }
 
     // Unused until fully implemented
    public Snapping snapping = new Snapping();
 
     void Start()
     {
         LastSelectedBuilding = SelectedBuilding;
         isBuildingEnabled = false;
 
     }
 
     public void ActivateBuildingmode()
     {
         isBuildingEnabled = true;
     }
 
     public void DeactivateBuildingmode()
     {
         isBuildingEnabled = false;
     }
 
     public void SelectBuilding(int id)
     {
         if (id < Building.Length && id >= 0)
         {
             LastSelectedBuilding = SelectedBuilding;
             SelectedBuilding = id;
         }
     }
 
     void Update()
     {
         if (!isBuildingEnabled)
         {
             if (ghost != null)
             {
                 Destroy(ghost);
                 ghostOn = false;
             }
                 
             return;
         }
             
 
         Ray ray;
         RaycastHit[] hit;
         ray = Camera.main.ScreenPointToRay(Input.mousePosition);
         hit = Physics.RaycastAll(ray, Mathf.Infinity);
     
         for (int i = 0; i < hit.Length; i++)
         {
             if (hit[i].collider.tag == TerrainCollisionTag)
             {
                 
 
                 if (SelectedBuilding != LastSelectedBuilding && ghost != null)
                 {
                     Destroy(ghost);
                     ghostOn = false;
                     LastSelectedBuilding = SelectedBuilding;
                     
                     break;
                 }
                 
                 if (!ghostOn)
                 {
                     ghost = (GameObject)Instantiate(Building[SelectedBuilding], 
                     new Vector3(hit[i].point.x,
                         hit[i].point.y, 
                         hit[i].point.z), 
                         Quaternion.identity);
 
                     ghost.name = ghost.name.Replace("(Clone)", "(Ghost)");
                     ghost.layer = 2; //ignore raycast layer
 
                     ghostCollision = ghost.AddComponent<BuildingCollision>();
         
                     ghostOn = true;    
                 }
     
                 if (ghost != null)
                 {
                     if (Input.GetMouseButtonDown(0) && !ghostCollision.Collided() && isFlat)
                     {
                         BuildingList bl = new BuildingList();
 
                         DestroyImmediate(ghost);
 
                         bl.buildingGameObject = (GameObject)Instantiate(Building[SelectedBuilding],
                         new Vector3(hit[i].point.x,
                             hit[i].point.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
                             hit[i].point.z),
                         Quaternion.identity);
 
                         string s = bl.buildingGameObject.name.Replace("(Clone)", "");
                         bl.buildingGameObject.name = s;
                         bl.buildingName = s;
                         bl.buildingGameObject.AddComponent<BuildingCollision>();
 
                         buildings.Add(bl);
 
                         ghostOn = false;
 
                         DeactivateBuildingmode();
 
                         break;
                     }
 
                     Vector3 ghostTargetPos = new Vector3(
                         hit[i].point.x,
                         hit[i].point.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
                         hit[i].point.z);
 
                     ghost.transform.position = ghostTargetPos;
 
                     isFlat = GroundFlat();
                         
                     if (ghostCollision.Collided() || !isFlat)
                     {
                         ghost.GetComponent<Renderer>().material.CopyPropertiesFromMaterial(Building[SelectedBuilding].GetComponent<Renderer>().sharedMaterial);
                         ghost.GetComponent<Renderer>().material.color = new Color(
                             1f,
                             0f, 
                             0f, 
                             0.6f);
                     }            
                     else if (!ghostCollision.Collided() && isFlat)
                     {
                         ghost.GetComponent<Renderer>().material.CopyPropertiesFromMaterial(Building[SelectedBuilding].GetComponent<Renderer>().sharedMaterial);
                         ghost.GetComponent<Renderer>().material.color = new Color(
                             0f,
                             1f, 
                             0f, 
                             0.6f);
                     }
             
                 }
             }    
         }
     }
 
     private bool GroundFlat()
     {
         RaycastHit[] buildingSlopeHitULAll;
         RaycastHit[] buildingSlopeHitURAll;
         RaycastHit[] buildingSlopeHitDLAll;
         RaycastHit[] buildingSlopeHitDRAll;
         RaycastHit[] buildingSlopeHitMAll;
 
         buildingSlopeHitULAll = Physics.RaycastAll(new Vector3(
             ghost.GetComponent<Collider>().transform.position.x - ghost.transform.localScale.x / 2,
             ghost.GetComponent<Collider>().transform.position.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
             ghost.GetComponent<Collider>().transform.position.z - ghost.transform.localScale.z / 2),
             Vector3.down, Mathf.Infinity);
 
         buildingSlopeHitURAll = Physics.RaycastAll(new Vector3(
             ghost.GetComponent<Collider>().transform.position.x + ghost.transform.localScale.x / 2,
             ghost.GetComponent<Collider>().transform.position.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
             ghost.GetComponent<Collider>().transform.position.z - ghost.transform.localScale.z / 2),
             Vector3.down, Mathf.Infinity);
 
         buildingSlopeHitDLAll = Physics.RaycastAll(new Vector3(
             ghost.GetComponent<Collider>().transform.position.x - ghost.transform.localScale.x / 2,
             ghost.GetComponent<Collider>().transform.position.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
             ghost.GetComponent<Collider>().transform.position.z + ghost.transform.localScale.z / 2),
             Vector3.down, Mathf.Infinity);
 
         buildingSlopeHitDRAll = Physics.RaycastAll(new Vector3(
             ghost.GetComponent<Collider>().transform.position.x + ghost.transform.localScale.x / 2,
             ghost.GetComponent<Collider>().transform.position.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
             ghost.GetComponent<Collider>().transform.position.z + ghost.transform.localScale.z / 2),
             Vector3.down, Mathf.Infinity);
 
         buildingSlopeHitMAll = Physics.RaycastAll(new Vector3(
             ghost.GetComponent<Collider>().transform.position.x,
             ghost.GetComponent<Collider>().transform.position.y + Building[SelectedBuilding].GetComponent<Collider>().transform.localScale.y / 2,
             ghost.GetComponent<Collider>().transform.position.z),
             Vector3.down, Mathf.Infinity);
 
         RaycastHit hitUL = new RaycastHit(), hitUR = new RaycastHit(), hitDL = new RaycastHit(), hitDR = new RaycastHit(), hitM = new RaycastHit();
 
         foreach (RaycastHit hit in buildingSlopeHitULAll)
         {
             if (hit.collider.tag == TerrainCollisionTag)
             {
                 hitUL = hit;
                 break;
             }
         }
         foreach (RaycastHit hit in buildingSlopeHitURAll)
         {
             if (hit.collider.tag == TerrainCollisionTag)
             {
                 hitUR = hit;
                 break;
             }
         }
         foreach (RaycastHit hit in buildingSlopeHitDLAll)
         {
             if (hit.collider.tag == TerrainCollisionTag)
             {
                 hitDL = hit;
                 break;
             }
         }
         foreach (RaycastHit hit in buildingSlopeHitDRAll)
         {
             if (hit.collider.tag == TerrainCollisionTag)
             {
                 hitDR = hit;
                 break;
             }
         }
         foreach (RaycastHit hit in buildingSlopeHitMAll)
         {
             if (hit.collider.tag == TerrainCollisionTag)
             {
                 hitM = hit;
                 break;
             }
         }
 
         if ((buildingSlopeHitULAll.Length > 0 ? hitUL.collider != null : false) &&
             (buildingSlopeHitURAll.Length > 0 ? hitUR.collider != null : false) &&
             (buildingSlopeHitDLAll.Length > 0 ? hitDL.collider != null : false) &&
             (buildingSlopeHitDRAll.Length > 0 ? hitDR.collider != null : false) &&
             (buildingSlopeHitMAll.Length > 0 ? hitM.collider != null : false))
         {
 
             if (HitDistanceSmallerEqual(hitUL, maxSlopeHigh) &&
                 HitDistanceSmallerEqual(hitUR, maxSlopeHigh) &&
                 HitDistanceSmallerEqual(hitDL, maxSlopeHigh) &&
                 HitDistanceSmallerEqual(hitDR, maxSlopeHigh) &&
                 HitDistanceSmallerEqual(hitM, maxSlopeHigh))
             {
                 return true;
             }
             else
                 return false;
         }
         else
             return false;
     }
 
     private bool ContainsTag(RaycastHit[] hitArr, string tag)
     {
         foreach (RaycastHit h in hitArr)
             if (h.collider.tag == tag)
                 return true;
 
         return false;
     }
 
     private bool ContainsTag(RaycastHit[] hitArr, string tag, out RaycastHit correctHit)
     {
         foreach (RaycastHit h in hitArr)
             if (h.collider.tag == tag)
             {
                 correctHit = h;
                 return true;
             }
 
         correctHit = new RaycastHit();
         return false;
     }
 
     private bool HitDistanceSmallerEqual(RaycastHit hit, float val)
     {
         if (hit.distance - (ghost.transform.localScale.y) <= val)
             return true;
 
         return false;
     }
 
     static void ClearConsole()
     {
         // This simply does "LogEntries.Clear()" the long way:
         var logEntries = System.Type.GetType("UnityEditorInternal.LogEntries,UnityEditor.dll");
         var clearMethod = logEntries.GetMethod("Clear", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
         clearMethod.Invoke(null, null);
     }
 }
     
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

4 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by MostNimbus · Mar 18, 2017 at 01:45 PM

Well, why not add Quaternion.Euler with params of transform.rotation. + 90? Then just make check for if(angle is 360){ set rotation to 0 } and assign it?

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

Answer by AnOrdinarySandwich · Mar 18, 2017 at 05:47 PM

Hi! Leerow is on the right track. Your instantiate code:

 ghost = (GameObject)Instantiate(Building[SelectedBuilding], 
                      new Vector3(hit[i].point.x,
                          hit[i].point.y, 
                          hit[i].point.z), 
                          Quaternion.identity);

Instead of using Quaternion.identity, use the correct rotational Quaternion :)

Comment
Add comment · Show 14 · 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 Skyfall106_Gaming · Mar 19, 2017 at 05:45 AM 0
Share

Hey! I am not quite sure what you mean as I am still learning scripting. Can you please explain just a bit better :) Thanks

avatar image AnOrdinarySandwich · Mar 19, 2017 at 04:31 PM 0
Share

Hey Skyfall, are you familiar with the term Quaternion? It's a rotational matrix, deter$$anonymous$$ing how the objects is rotated. Here's the Unity5 tutorial on Quaternions (it's only like 5 $$anonymous$$utes long to watch). Also, the code you can look at for an example is under LookAtScript, showing an example of how Quaternions can be used. And here's the scripting reference for Quaternions.

The ghost object mentioned above, you know where that's located in your code?

The call here Instantiate is the method used to create a game object copy of a prefab in code. In this case, it's accepting three arguments:

The item to spawn (in this case Building[SelectedBuilding])
The locational Vector3 where it spawns
The rotatational Quaternion

Quaternion.identity is a buildin rotation, defaulting to "no rotation" (as the unity docs call it). And as Leerow suggested, Quaterion.Euler() is a method that takes three arguments, rotation of x, y, and z (in degrees, not radians).

So, once you know which 90 degree angle snap location you want the building to have, ins$$anonymous$$d of using Quaternion.identity, simply replace it with Quaterion.Euler(yourXRotation, yourYRotation, yourZRotation).

avatar image Skyfall106_Gaming · Mar 19, 2017 at 11:09 PM 0
Share

Hey! I checked it out but thats in Javascript and it wouldnt connect with my code. Did i do something wrong?

avatar image AnOrdinarySandwich Skyfall106_Gaming · Mar 20, 2017 at 01:56 AM 0
Share

Post your code you tried. Also, the unity site has javascript and c# code available :)

avatar image Skyfall106_Gaming AnOrdinarySandwich · Mar 20, 2017 at 02:44 AM 0
Share
 if (!ghostOn)
                 {
                     ghost = (GameObject)Instantiate(Building[SelectedBuilding], 
                     new Vector3(hit[i].point.x,
                         hit[i].point.y, 
                         hit[i].point.z), 
                         var rotation = Quaternion.Euler(0, 30, 0);
Show more comments
avatar image Skyfall106_Gaming · Mar 20, 2017 at 08:53 PM 0
Share

Hey @AnOrdinarySandwich! (I notififed you as for some reason I couldnt reply to your comment.) It almost worked! I added it to my code but when i place it it had rotate the 90 degrees and then goes back to the way it was before. I cant change it either ): But still thank you so much for helping me and also I agree what your saying about scripting so starting tomorrow I am going to start learning! Thanks!

avatar image AnOrdinarySandwich Skyfall106_Gaming · Mar 20, 2017 at 10:09 PM 0
Share

Hi Skyfall, just a tad more! As user r_ge rightly pointed out, this "ghost" is a preview object, to show you how it will look once the building itself is actually Instantiated. If you'll take a look in the original code in your first post, around like line 133, you'll notice another Instantiate call. This is the actual building placement. And do you see the Quaternion.identity here too? That's why it's not rotated upon placement. Hopefully that's enough to help you plug in the rotation from the ghost!

avatar image Skyfall106_Gaming AnOrdinarySandwich · Mar 20, 2017 at 10:34 PM 0
Share

It kindove works if i dd it right. I changed the code that you said to the same code as you suggested. Im not dure if thats right but thats another problem. I also cant change it with a key. Im so sorry for continuously bugging you and I will give you some credit for your hard work :)

avatar image AnOrdinarySandwich Skyfall106_Gaming · Mar 20, 2017 at 11:04 PM 0
Share

Can you post the code. showing all changes that you've made so far? Then we can see about getting that working

avatar image Skyfall106_Gaming AnOrdinarySandwich · Mar 20, 2017 at 11:11 PM 0
Share
     if (!ghostOn)
                 {
                     GameObject buildingToCreate = Building[SelectedBuilding];
                     Vector3 buildingLocation = new Vector3(hit[i].point.x, hit[i].point.y, hit[i].point.z);
                     Quaternion buildingRotation = Quaternion.Euler(0, 90, 0);
 
                     //  ghost has already been declared, so we don't need to declare it again
                     ghost = (GameObject)Instantiate(buildingToCreate, buildingLocation, buildingRotation);
                     // snipped to conserve space
                 }
 
                     ghost.name = ghost.name.Replace("(Clone)", "(Ghost)");
                     ghost.layer = 2; //ignore raycast layer
 
                     ghostCollision = ghost.AddComponent<BuildingCollision>();
         
                     ghostOn = true;    
     
     
                 if (ghost != null)
                 {
                     if (Input.Get$$anonymous$$ouseButtonDown(0) && !ghostCollision.Collided() && isFlat)
                     {
                         BuildingList bl = new BuildingList();
 
                         DestroyImmediate(ghost);
 
                         GameObject buildingToCreate = Building[SelectedBuilding];
                         Vector3 buildingLocation = new Vector3(hit[i].point.x, hit[i].point.y, hit[i].point.z);
                         Quaternion buildingRotation = Quaternion.Euler(0, 90, 0);
 
                         //  ghost has already been declared, so we don't need to declare it again
                         ghost = (GameObject)Instantiate(buildingToCreate, buildingLocation, buildingRotation);
                         // snipped to conserve space

I had to get rid of the [...] as it caused errors in my console

Show more comments
Show more comments
avatar image
1

Answer by rbeldessi · Mar 19, 2017 at 06:41 PM

Store a quaternion previewRotation for your building preview (I'm assuming that's what ghost is), when the user hits whatever input for rotation:

 if(input)
     previewRotation = Quaternion.Euler(previewRotation.eulerAngles + new Vector3(0, 90, 0));

Then when you instantiate the final version of the building instead of using Quaternion.identity use previewRotation; then I assume you wouldn't want the preview to persist through different building placements so reset previewRotation to Quaternion.identity.

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

Answer by RGS-Aaron · Mar 19, 2017 at 04:43 PM

This is quite easy, the solution I would use is something like this:

 float objectRotation;
 
 void update(){
     if(Input.getButtonDown("MyRotateClockwisebutton")){
         objectRotation = objectRotation - 90;
     }
 }
 
 Instantiate code
 
 Instantiate(MyPrefab, myRotation, Quaternion.Euler(new Vector3(0, objectRotation, 0)));
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

318 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 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 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

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How to make drawable Paths 0 Answers

Making Building Placment rotatable 0 Answers

Raycasting not working? 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