How can i scale a cube to only one direction left? - c#

And then only to right and only to up and only down.
The main idea is to scale to one direction.
The problem is i'm not using the editor to add new empty gameobject or a cube.
I'm using a script to create a cube and a new empty gameobject.
In the editor in the scene window i have a cube already. And in the script i'm using this cube to create/duplicate another cube and creating new empty gameobject.
I tried to work like the answer here: The solution method 2.
Solution
But this solution is using the editor and i'm using a script.
What i tried so far:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Test : MonoBehaviour
{
public GameObject gameObjectToRaise;
public float raiseAmount;
public float raiseTotal = 50;
public float speed = 2;
public static bool raised = false;
public int x, z;
private List<GameObject> cubes;
private GameObject go;
public bool randomColor;
public Color[] colorChoices;
Vector3 lp;
Vector3 ls;
// Use this for initialization
void Start()
{
lp = gameObjectToRaise.transform.localPosition;
ls = gameObjectToRaise.transform.localScale;
go = new GameObject();
CreateCubes();
}
void Update()
{
if (DetectPlayer.touched == true)
{
if (raiseAmount < raiseTotal)
{
float raiseThisFrame = speed * Time.deltaTime;
if (raiseAmount + raiseThisFrame > raiseTotal)
{
raiseThisFrame = raiseTotal - raiseAmount;
}
raiseAmount += raiseThisFrame;
gameObjectToRaise.transform.localScale += new Vector3(raiseThisFrame, raiseThisFrame, 0);
go.transform.localScale += new Vector3(raiseThisFrame, raiseThisFrame, 0);
go.transform.position += Vector3.left * (speed / 2) * Time.deltaTime;
}
else
{
raised = true;
}
}
}
private List<GameObject> CreateCubes()
{
cubes = new List<GameObject>();
for (int a = 0; a < x; a++)
{
for (int b = 0; b < z; b++)
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
if (randomColor)
{
cube.GetComponent<Renderer>().material.color = colorChoices[Random.Range(0, (colorChoices.Length))];
}
cube.transform.position = new Vector3(lp.x - 1, lp.y, lp.z);
cube.transform.Rotate(0, 90, 0);
cubes.Add(cube);
}
}
go.transform.position = new Vector3(lp.x - 2,lp.y,lp.z);
go.transform.Rotate(0, 90, 0);
cubes[0].transform.parent = go.transform;
return cubes;
}
}
But again it's scaling the go var(New empty gameobject) on both sided left and right and i want only to the left.
In my first question it was marked as already answered but the solution in the link is when using the editor and i want to do it by script.

In my first question it was marked as already answered but the
solution in the link is when using the editor and i want to do it
by script.
It is still the-same solution. Create a cube then create an empty GameObject. Position that empty GameObject to the left side of the cube. Now make that cube a child a of that GameObject with childCube.transform.SetParent(thatObject.transform);. That's it.
Below is a helper class to do this. It can position the pivot point to any position. I provided CubePivotPoint enum to make it even easier. You can also pass in Vector3 position as a pivot point.
public class CUBE
{
public enum CubePivotPoint
{
MIDDLE, LEFT, RIGHT, UP, DOWN, FORWARD, BACK
}
//Takes CubePivotPoint Enum as pivot point
public static GameObject CreatePrimitive(CubePivotPoint pivot)
{
//Calculate pivot point
Vector3 cubePivot = createPivotPos(pivot);
//Create cube with the calculated pivot point
return createCubeWithPivotPoint(cubePivot);
}
//Takes Vector3 as pivot point
public static GameObject CreatePrimitive(Vector3 pivot)
{
//Create cube with the calculated pivot point
return createCubeWithPivotPoint(pivot);
}
private static Vector3 createPivotPos(CubePivotPoint pivot)
{
switch (pivot)
{
case CubePivotPoint.MIDDLE:
return new Vector3(0f, 0f, 0f);
case CubePivotPoint.LEFT:
return new Vector3(-0.5f, 0f, 0f);
case CubePivotPoint.RIGHT:
return new Vector3(0.5f, 0f, 0f);
case CubePivotPoint.UP:
return new Vector3(0f, 0.5f, 0f);
case CubePivotPoint.DOWN:
return new Vector3(0f, -0.5f, 0f);
case CubePivotPoint.FORWARD:
return new Vector3(0f, 0f, 0.5f);
case CubePivotPoint.BACK:
return new Vector3(0f, 0f, -0.5f);
default:
return default(Vector3);
}
}
private static GameObject createCubeWithPivotPoint(Vector3 pivot)
{
//Create a cube postioned at 0,0,0
GameObject childCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
//Create an empty parent object
GameObject parentObject = new GameObject("CubeHolder");
//Move the parent object to the provided pivot postion
parentObject.transform.position = pivot;
//Make the childcube to be child child of the empty object (CubeHolder)
childCube.transform.SetParent(parentObject.transform);
return parentObject;
}
}
Usage:
void Start()
{
GameObject cube = CUBE.CreatePrimitive(CUBE.CubePivotPoint.RIGHT);
StartCoroutine(scaleCube(cube.transform));
}
IEnumerator scaleCube(Transform trans)
{
while (true)
{
trans.localScale += new Vector3(0.1f, 0, 0);
yield return null;
}
}
As for integrating this into your current code, change
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
to
GameObject cube = CUBE.CreatePrimitive(CUBE.CubePivotPoint.RIGHT);.
then change cube.GetComponent<Renderer>() to cube.GetComponentInChildren<Renderer>() since the cube is now a child Object of another GameObject.

Related

How to execute a command if two gameobjects are at a certain position?

I am struggling with a problem, i couldn't find a solution untill now, maybe you can help me! So, i have a conveyor and random gameobjects spawning on it, and the conveyor transports the objects untill the end of it. On the conveyor i have a sort palette that i want to rotate at certain angles based on what gameobject spawned, but i want them to rotate only when the gameobject is close to the pallet, kind of sensor working thing, like the pallet has a sensor and when the object is at a certain distance, the pallet knows the angle he should rotate on. The objects move on the conveyor on the X axis, I want to know how to check when the gameobject reached the point, the code i am using below is not working. Thank you for your help!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//i have a conveyor with 2 bands next to eachother moving on opposite directions
public class Stackoverflow : MonoBehaviour
{
public Slider x;
public InputField inputspawn;
public InputField inputtime;
public Slider z;
public GameObject[] prefabs;
Vector3 V = new Vector3();
public GameObject coordX1, coordX2, coordZ1, coordZ2;
int spawnvalue;
float timevalue;
bool value = false;
public Slider paleta1;//slider that rotates 1st pallet
public Slider paleta2;//slider that rotates 2nd pallet
public GameObject verificationpoint;//when this point is reached by GO, the pallet should rotate
float[] unghiuri = { 164.6144f, 205.6429f, 87.5875f, 164.6144f };//angles for 1st pallet
float[] ung = { 154.3571f, 90f, 90f, 90f};// angles for 2nd pallet
public int T;
public GameObject paleta1go, paleta2go;// pallet 1 and 2
public float delta;
public float dist;
void Start()
{
Vector3 position = new Vector3(UnityEngine.Random.Range( coordX1.transform.position.x, coordX2.transform.position.x), 3f, UnityEngine.Random.Range(coordZ1.transform.position.z, coordZ2.transform.position.z));
T = UnityEngine.Random.Range(0, prefabs.Length);
Instantiate(prefabs[T], position, Quaternion.identity);
paleta1.value = unghiuri[T];
paleta2.value = ung[T];
StartCoroutine(Spawn());
}
void Update()
{
if (value == true)
{
Vector3 position = new Vector3(UnityEngine.Random.Range(coordX1.transform.position.x, coordX2.transform.position.x), 3f, UnityEngine.Random.Range(coordZ1.transform.position.z, coordZ2.transform.position.z));
V = position;
spawnvalue = int.Parse(inputspawn.text);
timevalue = float.Parse(inputtime.text);
dist = Vector3.Distance(paleta1go.transform.position, prefabs[T].transform.position);
if (prefabs[T].transform.position.x == verificationpoint.transform.position.x)//that's how i verify if the GO reaches verification point
{
paleta1.value = unghiuri[T];
paleta2.value = ung[T];
}
}
}
IEnumerator Spawn()
{
while (true)
{
if(value)
for(int i = 0; i < spawnvalue; ++i)
{
Vector3 position = new Vector3(UnityEngine.Random.Range(coordX1.transform.position.x, coordX2.transform.position.x), 3f, UnityEngine.Random.Range(coordZ1.transform.position.z, coordZ2.transform.position.z));
V = position;
T = UnityEngine.Random.Range(0, prefabs.Length);
Instantiate(prefabs[T], V, Quaternion.identity);
}
yield return new WaitForSeconds(timevalue);
}
}
public void ToggleState(bool t)
{
value = !value;
}
}

Line Casting: GameObject Face End Point of Ray

I'm trying to make the enemy object face the end of the line cast. The code I have locks the ray onto the player when detected properly. My problem here is that my enemy sprite is a grandchild of the Rigidbody2D and I'm using eulerAngles to change the sprites direction. Here is the code I have:
using UnityEngine;
public class PlayerDetection : MonoBehaviour
{
public Transform origin, end, player;
public float radarSpd;
public bool playerDetected;
public static bool playerIsDetected;
private int playerLayer = 1 << 8;
private Rigidbody2D enemyRb;
private Vector3 facePlayer;
private void Start()
{
enemyRb = GetComponentInParent<Rigidbody2D>();
playerIsDetected = false;
}
private void Update()
{
PlayerDetector();
if (playerDetected == false)
{
Radar();
}
else { PlayerIsDetected(); }
}
void PlayerDetector()
{
Debug.DrawLine(origin.position, end.position, Color.red);
playerDetected = Physics2D.Linecast(origin.position, end.position, playerLayer);
}
void Radar()
{
end.RotateAround(origin.position, Vector3.forward, radarSpd * Time.deltaTime);
}
void PlayersPosition()
{
facePlayer = player.position - enemyRb.transform.GetChild(0).GetChild(0).position;
float enemyRot = Mathf.Atan2(facePlayer.y, facePlayer.x) * Mathf.Rad2Deg;
enemyRb.transform.GetChild(0).GetChild(0).eulerAngles = new Vector3(0, 0, enemyRot);
}
void PlayerIsDetected()
{
if(playerDetected == true)
{
playerIsDetected = true;
end.position = player.position;
PlayersPosition();
}
}
}
The main focus for this code that I need help is here:
void PlayersPosition()
{
facePlayer = player.position - enemyRb.transform.GetChild(0).GetChild(0).position;
float enemyRot = Mathf.Atan2(facePlayer.y, facePlayer.x) * Mathf.Rad2Deg;
enemyRb.transform.GetChild(0).GetChild(0).eulerAngles = new Vector3(0, 0, enemyRot);
}
The enemy does not face the player at all and doesn't seem to rotate much at all as the player moves around the screen.
I've tried applying a rotationSpeed variable and multiplied it by enemyRot multiplied by Time.deltaTime but didn't work either.
enemyRb.transform.GetChild(0).GetChild(0).eulerAngles = new Vector3(0, 0, enemyRot * rotSpd * Time.deltaTime);
I've been stuck on this for a week now and really need some help resolving this issue! So how can I achieve my desired rotation by use of eulerAngles?
Turned out that I was doing too much math. Here is the solution:
Edit: My enemy is facing in an upward position. This code works on that scale.
void PlayersPosition()
{
facePlayer = player.position - enemyRb.transform.GetChild(0).GetChild(0).position;
enemyRb.transform.GetChild(0).GetChild(0).up = -facePlayer;
}

Multiple clones of model spawning in target (Vuforia and Unity)

I am trying to place a sphere on a ground plane and on a button click remove the sphere and place a cube.
This is the script attached to the AR camera object.
using UnityEngine;
using Vuforia;
using System.Collections;
public class ModelSwapper : MonoBehaviour {
public AnchorStageBehaviour theTrackable;
public Transform myModelPrefab;
private bool mSwapModel = false;
// Use this for initialization
void Start () {
Transform myModelTrf = GameObject.Instantiate(myModelPrefab) as Transform;
myModelTrf.parent = theTrackable.transform;
myModelTrf.localPosition = new Vector3(0f, 0f, 0f);
myModelTrf.localRotation = Quaternion.identity;
myModelTrf.localScale = new Vector3(0.05f, 0.05f, 0.05f);
myModelTrf.gameObject.active = true;
}
// Update is called once per frame
void Update () {
if (mSwapModel && theTrackable != null) {
SwapModel();
mSwapModel = false;
}
}
void OnGUI() {
if (GUI.Button (new Rect(50,50,120,40), "Swap Model")) {
mSwapModel = true;
}
}
private void SwapModel() {
GameObject trackableGameObject = theTrackable.gameObject;
//disable any pre-existing augmentation
for (int i = 0; i < trackableGameObject.transform.GetChildCount(); i++)
{
Transform child = trackableGameObject.transform.GetChild(i);
child.gameObject.active = false;
}
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
// Re-parent the cube as child of the trackable gameObject
cube.transform.parent = theTrackable.transform;
// Adjust the position and scale
// so that it fits nicely on the target
cube.transform.localPosition = new Vector3(0, 0.2f, 0);
cube.transform.localRotation = Quaternion.identity;
cube.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
// Make sure it is active
cube.active = true;
}
}
But instead, it spawns multiple cubes along with the sphere.
Multiple clones
Since, there isn't much documentation or anything else on Vuforia ground plane, it's hard to get things done. Why is this behaving strange?
You could avoid the Update and it should fix your issue, replace these two methods in your script with the following:
void Update () {
}
void OnGUI() {
if (GUI.Button (new Rect(50,50,120,40), "Swap Model")) {
if(theTrackable)
{
SwapModel();
}
}
}

How can i click and drag a gameobject with the mouse?

Created new script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mouseDrag : MonoBehaviour
{
float distance = 10;
void OnMouseDrag()
{
Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance);
Vector3 objPosition = Camera.main.ScreenToWorldPoint(mousePosition);
transform.position = objPosition;
}
}
Then in another script in the Start function i'm creating 4 cubes and add the mouseDrag to each cube. But when running and clicking and dragging nothing happen. I'm not getting any errors or exceptions.
void Start()
{
lp = gameObjectToRaise.transform.localPosition;
ls = gameObjectToRaise.transform.localScale;
List<GameObject> cubes = new List<GameObject>();
GameObject cube = Cube.CreatePrimitive(Cube.CubePivotPoint.UPLEFT);
GameObject cube1 = Cube.CreatePrimitive(Cube.CubePivotPoint.UPRIGHT);
GameObject cube2 = Cube.CreatePrimitive(Cube.CubePivotPoint.BACKUP);
GameObject cube3 = Cube.CreatePrimitive(Cube.CubePivotPoint.UPRIGHT);
cubes.Add(cube);
cubes.Add(cube1);
cubes.Add(cube2);
cubes.Add(cube3);
cube.GetComponentInChildren<Renderer>().material.color = Color.blue;
cube1.GetComponentInChildren<Renderer>().material.color = Color.red;
cube2.GetComponentInChildren<Renderer>().material.color = Color.green;
cube3.GetComponentInChildren<Renderer>().material.color = Color.yellow;
cube.transform.position = new Vector3(lp.x, lp.y, lp.z - 0.5f);
cube1.transform.position = new Vector3(lp.x, lp.y, lp.z);
cube2.transform.position = new Vector3(lp.x, lp.y, lp.z + 5);
cube3.transform.position = new Vector3(lp.x + 5, lp.y, lp.z);
cube1.transform.Rotate(0, 90, 0);
cube3.transform.Rotate(0, 90, 0);
StartCoroutine(scaleCube(cube.transform));
StartCoroutine(scaleCube(cube1.transform));
StartCoroutine(scaleCube(cube2.transform));
StartCoroutine(scaleCube(cube3.transform));
foreach (GameObject go in cubes)
{
go.AddComponent<mouseDrag>();
}
}
IEnumerator scaleCube(Transform trans)
{
while (raiseAmount < raiseTotal)
{
raiseAmount += 1f;
trans.localScale += new Vector3(speed * Time.deltaTime, speed * Time.deltaTime, 0);
yield return null;
}
}
}
I just tried now with a single cube gameobject i added for testing it
and it's working fine. But when i'm using the cubes using the CUBE
class helper it's not working.
In this case, the mouseDrag script should be attached to the child cube(not the CubeHolder object).After that, you should be moving the parent of the cube which is "CubeHolder".
If you ever move the child cube, you will break the pivot point.
Simply change
transform.position = objPosition;
to
transform.parent.position = objPosition;
then attach the mouseDrag script to the child cube not the "CubeHolder".
Maybe the problem is that it's attaching the script to the
parentObject "CubeHolder" and not to the created cubes ?
Yes. OnMouseDrag will only be called if attached to an Object with a Collider and the child cube is the only object with the Collider. The parent object is only there to be used as a pivot point feature.
NOTE:
You should not use OnMouseDrag for this. You should be dragging the cube/Object with the new UI event. There are many of the callback functions listed in this answer.
The script below is something you should be using. Attach the CubeDrag sctipt to the child cube then change everything that says transform.position to transform.parent.position.
using UnityEngine;
using UnityEngine.EventSystems;
public class CubeDrag: MonoBehaviour, IPointerDownHandler, IDragHandler, IEndDragHandler
{
Camera mainCamera;
float zAxis = 0;
Vector3 clickOffset = Vector3.zero;
// Use this for initialization
void Start()
{
addEventSystem();
zAxis = transform.position.z;
}
public void OnPointerDown(PointerEventData eventData)
{
Vector3 tempPos = eventData.position;
tempPos.z = Vector3.Distance(transform.position, Camera.main.transform.position);
clickOffset = transform.position - mainCamera.ScreenToWorldPoint(tempPos);
Debug.Log("Mouse Down");
}
public void OnDrag(PointerEventData eventData)
{
Vector3 tempPos = eventData.position;
tempPos.z = Vector3.Distance(transform.position, Camera.main.transform.position);
Vector3 tempVec = mainCamera.ScreenToWorldPoint(tempPos) + clickOffset;
tempVec.z = zAxis;
transform.position = tempVec;
Debug.Log("Dragging Cube");
}
public void OnEndDrag(PointerEventData eventData)
{
}
void addEventSystem()
{
mainCamera = Camera.main;
if (mainCamera.GetComponent<PhysicsRaycaster>() == null)
mainCamera.gameObject.AddComponent<PhysicsRaycaster>();
EventSystem eveSys = GameObject.FindObjectOfType(typeof(EventSystem)) as EventSystem;
if (eveSys == null)
{
GameObject tempObj = new GameObject("EventSystem");
eveSys = tempObj.AddComponent<EventSystem>();
}
StandaloneInputModule stdIM = GameObject.FindObjectOfType(typeof(StandaloneInputModule)) as StandaloneInputModule;
if (stdIM == null)
stdIM = eveSys.gameObject.AddComponent<StandaloneInputModule>();
}
}

Set appropriate Collider type for each Mesh that gets created

I'm generating a bunch of basic sphere and capsule mesh objects at runtime in a 3D fractal-based piece I'm working on, and I'm stuck on how to apply the appropriate Collider type when each object gets created.
My script randomly selects from either spheres or capsules and arranges them based on a range of orientation possibilities. I need help on how to assign the appropriate Collider when each mesh gets created.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class BuildFractal : MonoBehaviour
{
public Mesh[] meshes;
public Material material;
public Material[,] materials;
private Rigidbody rb;
public int maxDepth; // max children depth
private int depth;
public float childScale; // set scale of child objects
public float spawnProbability; // determine whether a branch is created or not
public float maxRotationSpeed; // set maximium rotation speed
private float rotationSpeed;
public float maxTwist;
public Text positionText;
public int objectMass;
// Create arrays for direction and orientation data
private static Vector3[] childDirections = {
Vector3.up,
Vector3.right,
Vector3.left,
Vector3.forward,
Vector3.back,
// Vector3.down
};
private static Quaternion[] childOrientations = {
Quaternion.identity,
Quaternion.Euler(0f, 0f, -90f),
Quaternion.Euler(0f, 0f, 90f),
Quaternion.Euler(90f, 0f, 0f),
Quaternion.Euler(-90f, 0f, 0f),
// Quaternion.Euler(180f, 0f, 0f)
};
private void Start ()
{
Rigidbody rb;
rotationSpeed = Random.Range(-maxRotationSpeed, maxRotationSpeed);
transform.Rotate(Random.Range(-maxTwist, maxTwist), 0f, 0f);
if (materials == null)
{
InitializeMaterials();
}
// Select from random range of meshes
gameObject.AddComponent<MeshFilter>().mesh = meshes[Random.Range(0, meshes.Length)];
// Select from random range of colors
gameObject.AddComponent<MeshRenderer>().material = materials[depth, Random.Range(0, 2)];
// Add Rigigbody to each object
rb = gameObject.AddComponent<Rigidbody>();
rb.useGravity = false;
rb.mass = objectMass;
// Create Fractal Children
if (depth < maxDepth)
{
StartCoroutine(CreateChildren());
}
}
private void Update ()
{
transform.Rotate(0f, rotationSpeed * Time.deltaTime, 0f);
}
private void Initialize (BuildFractal parent, int childIndex)
{
maxRotationSpeed = parent.maxRotationSpeed;
// copy mesh and material references from parent object
meshes = parent.meshes;
materials = parent.materials;
maxTwist = parent.maxTwist;
// set depth and scale based on variables defined in parent
maxDepth = parent.maxDepth;
depth = parent.depth + 1;
childScale = parent.childScale;
transform.parent = parent.transform; // set child transform to parent
// transform.localScale = Vector3.one * childScale;
transform.localScale = Vector3.one * Random.Range(childScale / 10, childScale * 1);
transform.localPosition = childDirections[childIndex] * (Random.Range((0.1f + 0.1f * childScale),(0.9f + 0.9f * childScale)));
transform.localRotation = childOrientations[childIndex];
spawnProbability = parent.spawnProbability;
}
private void InitializeMaterials ()
{
materials = new Material[maxDepth + 1, 2];
for (int i = 0; i <= maxDepth; i++)
{
float t = i / (maxDepth - 1f);
t *= t;
// Create a 2D array to hold color progressions
materials[i, 0] = new Material(material);
materials[i, 0].color = Color.Lerp(Color.gray, Color.white, t);
materials[i, 1] = new Material(material);
materials[i, 1].color = Color.Lerp(Color.white, Color.cyan, t);
}
// materials[maxDepth, 0].color = Color.white;
materials[maxDepth, 1].color = Color.white;
}
private IEnumerator CreateChildren ()
{
for (int i = 0; i < childDirections.Length; i++)
{
if (Random.value < spawnProbability)
{
yield return new WaitForSeconds(Random.Range(0.1f, 1.5f));
new GameObject("Fractal Child").AddComponent<BuildFractal>().Initialize(this, i);
}
}
}
/*void OnCollisionEnter(Collision col)
{
if(col.gameObject.name == "Fractal Child")
{
Destroy(this.gameObject);
}
}*/
}
Add a mesh collider after you instantiate and set the same mesh, job done!
http://docs.unity3d.com/ScriptReference/MeshCollider.html
that should sort it out programmatically

Categories