List of Transforms editable from Inspector - c#

I'm working on Unity 5, and I need to create a list of transforms in order to modify them in the inspector (position and rotation) to emulate a different camera. This emulation is for a demo, like a camera moving on its own during the demo.
I currently have a list of transforms, but I don't know how to make them modifiable in the inspector and change their position at runtime?
Edit: 18/11/15
Here is the solution that if find with a help of a friend of mine more aware of what really does unity, hope it will help you and thanks again for all your reply it helped me a lot :D :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MoveCamera : MonoBehaviourSingleton<MoveCamera>
{
public List<Transform> cameraPositions = new List<Transform>();
private Transform m_Target;
private float m_Speed;
private bool m_Translate;
private bool m_Rotate;
public void SwitchToNext(int index, float speed)
{
m_Target = cameraPositions[index];
m_Translate = true;
m_Rotate = true;
}
public void Update()
{
if (m_Target != null && (m_Translate || m_Rotate))
{
float ratio = Time.deltaTime * m_Speed;
transform.position = Vector3.Lerp(transform.position, m_Target.position, ratio);
transform.rotation = Quaternion.Slerp(transform.rotation, m_Target.rotation, ratio);
if (Vector3.Distance(transform.position, m_Target.position) < 0.001f)
{
transform.position = m_Target.position;
m_Translate = false;
}
if (Quaternion.Angle(transform.rotation, m_Target.rotation) < 0.001f)
{
transform.rotation = m_Target.rotation;
m_Rotate = false;
}
}
}
}

Ok lets see if this helps you.(i will write my code assuming you want this)
You have x gameObjects in your scene.
You will need a GameObject List. Lets say you get them by doing
public List<GameObject> myObjectList = new List<GameObject>();
public List<Transform> myTransformList = new List<Transform>();
myObjectList = GameObject.FindGameObjectsWithTag("YourCustomTagHere");
foreach(Gameobject g in myObjectList)
{
myTransformList.Add(g.transform);
}
I dont know if this code works, i cant test it right now, but i think the logic is there. Go ahead and try a few things, give some feedback whether you made it or not.

I would suggest just a simple public list in your MoveCamera script and then dragging the targets into that list. Doing it this way you have full control over the order of the objects and thus you can do animated transitions from camera position n to n + 1.
public List<Transform> cameraPositions = new List<Transform> ();
Maybe a simple sequence does not fit your requirements and you need a more sophisticated way to decide which position is allowed to switch to which other position. In this case I'd suggest a helper script e.g. CameraTransition.cs. Here you can place your check logic and definition parameters.
Attach this to every allowed target position object and replace the list in MoveCamera by List<CameraTransition>.

Related

Can only spawn one object at once in unity

In my game I have a game object called ExclamationMark which I want to spawn above enemies heads when the player gets into range and they become "Alerted".
I've made this simple script to do that, but for some reason it will only work on one game object.
My enemy script:
void CheckForPlayer()
{
// Define player and get position
var player = GameObject.FindWithTag("Player");
var playerPos = (int)player.transform.position.x;
if (transform.Find("Graphics"))
{
// Define gameobject position
var enemyPos = transform.Find("Graphics").gameObject.transform.position.x;
// Define range to spawn tiles in
var range = 5;
var rangeInfront = enemyPos + range;
var rangeBehind = enemyPos - range;
if (playerPos >= rangeBehind && playerPos <= rangeInfront)
{
enemyIsActive = true;
if (transform.Find("ExclamationMark"))
{
var exMark = transform.Find("ExclamationMark").gameObject.GetComponent<ExclamationMarkSpawn>();
exMark.SpawnExclamationMark();
}
}
else
{
enemyIsActive = false;
}
}
}
My ! script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExclamationMarkSpawn : MonoBehaviour {
public GameObject spawnPos;
public GameObject exclamationMark;
public GameObject exclamationMarkAudio;
public void SpawnExclamationMark()
{
StartCoroutine(GameObject.FindGameObjectWithTag("MainCamera").GetComponent<CameraShake>().Shake(0.2f, 0.2f, 0.2f));
Instantiate(exclamationMark, spawnPos.transform.position, Quaternion.identity);
if (exclamationMarkAudio)
Instantiate(exclamationMarkAudio, spawnPos.transform.position, Quaternion.identity);
StartCoroutine(DestroyExclamationMark());
}
IEnumerator DestroyExclamationMark()
{
yield return new WaitForSeconds(1);
var children = new List<GameObject>();
foreach (Transform child in transform) children.Add(child.gameObject);
children.ForEach(child => Destroy(child));
}
}
Just to be sure: I assume every player has its own instance of both of your scripts attached (some maybe nested further in their own hierarchy).
I assume that since you are using transform.Find which looks for the object by name within it's own children.
In general using Find and GetComponent over and over again is very inefficient! You should in both classes rather store them to fields and re-use them. Best would be if you can actually already reference them via the Inspector and not use Find and GetComponent at all.
In general finding something by name is always error prone. Are you sure they are all called correctly? Or are others maybe further nested?
Note: Find does not perform a recursive descend down a Transform hierarchy.
I would prefer to go by the attached components. You say it has e.g. a RigidBody. If this is the only Rigidbody component in the hierarchy below your objects (usually this should be the case) then you could instead rather simply use
// pass in true to also get disabled or inactive children
Rigidbody graphics = GetComponentInChildren<Rigidbody>(true);
the same for the ExclamationMarkSpawn
// Would be even beter if you already reference these in the Inspector
[SerializeField] private Rigidbody graphics;
[SerializeField] private ExclamationMarkSpawn exclamationMark;
[SerializeField] private Transform player;
private void Awake()
{
if(!player) player = GameObject.FindWithTag("Player");
if(!graphics) graphics = GetComponentInChildren<Rigidbody>(true);
if(!exclamationMark) exclamationMark = GetComponentInChildren<ExclamationMarkSpawn>(true);
}
private void CheckForPlayer()
{
// If really needed you can also after Awake still use a lazy initialization
// this adds a few later maybe unnecessary if checks but is still
// cheaper then using Find over and over again
if(!player) player = FindWithTag("Player");
if(!graphics) graphics = GetComponentInChildren<Rigidbody>(true);
if(!exclamationMark) exclamationMark = GetComponentInChildren<ExclamationMarkSpawn>(true);
var playerPos = (int)player.position.x;
// always if making such a check also give a hint that something might be missing
if (!graphics)
{
// by adding "this" you can now simply click on the message
// in the console and it highlights the object where this is happening in the hierarchy
Debug.LogWarning("graphics is missing here :'( ", this);
return;
}
// Define gameobject position
var enemyPos = graphics.transform.position.x;
// Define range to spawn tiles in
// this entire block can be shrinked down to
if (Mathf.Abs(playerPos - enemyPos) <= 5)
{
enemyIsActive = true;
if (exclamationMark) exclamationMark.SpawnExclamationMark();
}
else
{
enemyIsActive = false;
}
}
The same also in ExclamationMarkSpawn.cs.
I would additionally only allow 1 exclamation mark being visible at the same time. For example when a player jitters in the distance especially assuming both, the player and the enemy, I would move the entire instantiation to the routine and use a flag. Especially since this is called every frame in Update while the player stays in the range!
Also re-check and make sure your enemies are not maybe referencing the same spawnPos and thus all instantiating their exclamation marks on top of each other.
public class ExclamationMarkSpawn : MonoBehaviour
{
public Transform spawnPos;
public GameObject exclamationMark;
public GameObject exclamationMarkAudio;
[SerializeField] private CameraShake cameraShake;
// only serialized for debug
[SerializeField] private bool isShowingExclamation;
private void Awake()
{
if(!cameraShake) cameraShake = Camera.main.GetComponent<CameraShake>();
// or assuming this component exists only once in the entire scene anyway
if(!cameraShake) cameraShake = FindObjectOfType<CameraShake>();
}
public void SpawnExclamationMark()
{
StartCoroutine(ShowExclamationMark());
}
private IEnumerator ShowExclamationMark()
{
// block concurrent routine call
if(isShowingExclamation) yield brake;
// set flag blocking concurrent routines
isShowingExclamation = true;
// NOTE: Also for this one you might want to rather have a flag
// multiple enemy instances might call this so you get concurrent coroutines also here
StartCoroutine(cameraShake.Shake(0.2f, 0.2f, 0.2f));
Instantiate(exclamationMark, spawnPos.position, Quaternion.identity);
if (exclamationMarkAudio) Instantiate(exclamationMarkAudio, spawnPos.position, Quaternion.identity);
yield return new WaitForSeconds(1);
var children = new List<GameObject>();
foreach (var child in transform.ToList()) children.Add(child.gameObject);
children.ForEach(child => Destroy(child));
// give the flag free
isShowingExclamation = false;
}
}
Try this;
if (transform.Find("ExclamationMark"))
{
var exMark = transform.Find("ExclamationMark").gameObject.GetComponent<ExclamationMarkSpawn>();
exMark.SpawnExclamationMark(transform.position); //Add transform.position here
}
public void SpawnExclamationMark(Vector3 EnemyPos)
{
StartCoroutine(GameObject.FindGameObjectWithTag("MainCamera").GetComponent<CameraShake>().Shake(0.2f, 0.2f, 0.2f));
Instantiate(exclamationMark, EnemyPos, Quaternion.identity);
if (exclamationMarkAudio)
Instantiate(exclamationMarkAudio, EnemyPos, Quaternion.identity);
StartCoroutine(DestroyExclamationMark());
}

Move spawn object to random position

I have a spawner object. Every time a gameobject is spawned, I want that object to move randomly (wandering). The problem in my script is that the gameobject movement is very random (jittery). How can I solve this?
void Start ()
{
InvokeRepeating("SpawnNPC", Spawntime, Spawntime);
}
// Update is called once per frame
void Update () {
population = GameObject.FindGameObjectsWithTag("NPCobject");
for (int i = 0; i < population.Length; i++)
{
getNewPosition();
if (population[i].transform.position != pos)
{
population[i].transform.position = Vector3.MoveTowards(population[i].transform.position, pos, .1f);
}
}
}
void getNewPosition()
{
float x = Random.Range(-22, 22);
float z= Random.Range(-22, 22);
pos = new Vector3(x, 0, z);
}
I made the New randomize vector in different method, because I plan to change it with pathfinder function and make it in different thread/task.
You are choosing a new direction every single frame. That will always be very jittery. You wan't to only change direction after, at least, a small interval. Here is a link to one way to do that from Unity's website. https://docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.html
What about using Navigation? As you said wandering, I thought it would give you a nice result and also make your code simple.
The following screenshot is a sample with Navigation. The moving game objects are also changing their direction nicely, although it cannot be seen in the sample because the game object is capsule...
Ground game object in the sample program has NavMesh. See here to build NavMesh.
Agent game object has NavMeshAgent Component. See here to set it up.
Th Behaviour class below is for Agent game object.
using UnityEngine;
using UnityEngine.AI;
public class NavAgentBehaviour : MonoBehaviour {
public Transform[] Destinations { get; set; }
// Use this for initialization
void Start ()
{
InvokeRepeating("changeDestination", 0f, 3f);
}
void changeDestination()
{
var agent = GetComponent<NavMeshAgent>();
agent.destination = Destinations[Random.Range(0, Destinations.Length)].position;
}
}
The next Behaviour class is just for spawning the Agent and setting up the destinations. On Unity, set it to whatever game object in the scene, and allocate game objects to the fields.
using UnityEngine;
public class GameBehaviour : MonoBehaviour {
public GameObject Agent;
public Transform SpawnPoint;
public Transform Destination1;
public Transform Destination2;
public Transform Destination3;
// Use this for initialization
void Start()
{
Agent.SetActive(false);
InvokeRepeating("Spawn", 0f, 2f);
}
void Spawn() {
var newAgent = Instantiate(Agent);
newAgent.GetComponent<NavAgentBehaviour>().Destinations = new[] { Destination1, Destination2, Destination3 };
newAgent.transform.position = SpawnPoint.position;
newAgent.SetActive(true);
}
}
Increase the number of destination, to make the moves look more random. By the way, the destinations do not need to be specified by game objects, which is only for making it easy to see the sample program's behaviour.
The source of the jitteriness comes from the fact that you are updating the position to move every frame so your objects never have a consistent location to move to. I would instead suggest attaching a new script to each of your objects that individually handles their movement. In that script you could do something like the following, which has a delay to keep the target position for more than 1 frame.
float delaytimer;
Vector3 pos;
void Start () {
getNewPosition(); // get initial targetpos
}
void Update () {
delaytimer += Time.deltaTime;
if (delaytimer > 1) // time to wait
{
getNewPosition(); //get new position every 1 second
delaytimer = 0f; // reset timer
}
transform.position = Vector3.MoveTowards(transform.position, pos, .1f);
}
void getNewPosition()
{
float x = Random.Range(-22, 22);
float z= Random.Range(-22, 22);
pos = new Vector3(x, 0, z);
}
You are changing the direction they are moving in every frame, thats what is causing the jitter.
You could wait a few moments before you change the direction, perhaps something like this.
// Outside update
float betweenChanges = 2;
float lastChange = 0;
// Inside update
if(Time.realtimeSinceStartup > lastChange)
{
// Change directions
// ...
lastChange = Time.realTimeSinceStart + betweenChanges;
}
You could also solve this by using InvokeRepeating or a Coroutine.
If you dont want all the NPC's to change direction at the same time and still plan on controlling every NPC from the same class like in your example, you should perhaps add a timer for each NPC instance instead and use that to decide when to change its direction.
A better idea would be to let each NPC have its own Movement-script.

Moving objects back and forth [duplicate]

This question already has an answer here:
Move GameObject back and forth
(1 answer)
Closed 5 years ago.
I'm trying to move multiple objects, simultaneously from Point A to Point B and back again, looped to serve as obstacles in blocking the player.
I've tried
StartCoroutine(Oscillate(OscillationFunction.Sine, 1f));
public IEnumerator Oscillate(OscillationFunction method, float scalar)
right = GameObject.FindGameObjectsWithTag("MovingObs2");
foreach (GameObject r in right)
{
startPos = r.transform.position;
v = startPos;
v.x = (r.transform.position.x + (Mathf.Cos(Time.time) * scalar));
r.transform.position = v;
yield return new WaitForSeconds(2);
r.transform.position = startPos;
}
and others, but they're all difficult to contain within a desirable distance and speed from the starting position. It's too fast, and too far.
and I tried a seemingly simpler line, which is easier to understand, for me.
v.x = l.transform.position.x + speed * Time.deltaTime;
l.transform.position = v;
but since i'm using an array in a foreach loop, i don't know how to preserve each GameObjects' transform.position, so that it can be used as a condition to reverse the direction of the objects' movement every time it reaches either Point A, or point B.
if (l.transform.position.x <= startPos.x || l.transform.position.x >= startPos.x + endPos.x)
{
speed *= -1;
}
edit: I apologize if I asked a duplicate question, I thought it was different due to the number of objects involved in an array.
I tried to assume to resolve all your question, please see the code below.
Time.deltaTime is not needed, since your code (and my) using the Time.time to calculate each time the position of the object.
I also would recommend (if possible) to not put all in on script, but give each object a swing script and also try to not use the CoRoutine. But to answer your question I show you how to do it.
I have created an internal class, to store in the "Init" the targeted gameobjects and their startPosition in a list. Later you can simply loop throu this list and always have the start position.
You need an endless loop in the "Osciallate" routine and need to wait each turn. In your example you put the Wait on the wrong place, so it waits after moving each object and stops after the first run throu all of this objects.
Here the code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OscilateObs : MonoBehaviour {
// internal class where all gameobjects and their startposition will be saved
internal class OscGameObjects
{
public GameObject gameObject;
public Vector3 startPosition;
}
// Here the information of all gameObjects stored in a list
private List<OscGameObjects> objectList;
public float updateSpeed = 0.05f;
public float oscScalar = 2f;
public enum OscillationFunction {
Sine = 1
}
void Start () {
// First, the gameobjects have to saved to our internal List
InitializeOscGameObjects();
// Start the Corotine
StartCoroutine(Oscillate(OscillationFunction.Sine, oscScalar));
}
private void InitializeOscGameObjects()
{
var objects = GameObject.FindGameObjectsWithTag("MovingObs2");
objectList = new List<OscGameObjects>();
foreach (var o in objects)
{
var oscObject = new OscGameObjects();
oscObject.gameObject = o;
oscObject.startPosition = o.transform.position;
objectList.Add(oscObject);
}
}
public IEnumerator Oscillate(OscillationFunction method, float scalar)
{
// Loop forever
while(true)
{
foreach (var element in objectList)
{
var currentPosition = element.gameObject.transform.position;
currentPosition.x = element.startPosition.x + Mathf.Cos(Time.time) * scalar;
element.gameObject.transform.position = currentPosition;
}
yield return new WaitForSeconds(updateSpeed);
}
}
}
EDIT:
I forgot to meantion:
1) I would recommend to use "Animation" Component for the movement and not using C# at all, so you can change the behaviour if needed and you are more flexible.
2) I would also recommend if possible to make a parent "GameObject" and moving only this and put the "MovingOb2" simply as child objects.
EDIT2:
Adding a delay increment for each object, so they not running syncron:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OscilateObs : MonoBehaviour {
// internal class where all gameobjects and their startposition will be saved
internal class OscGameObjects
{
public GameObject gameObject;
public Vector3 startPosition;
public float waitCount;
}
// Here the information of all gameObjects stored in a list
private List<OscGameObjects> objectList;
public float updateSpeed = 0.05f;
public float oscScalar = 2f;
public float waitIncrementTime = 0.01f;
public enum OscillationFunction {
Sine = 1
}
void Start () {
// First, the gameobjects have to saved to our internal List
InitializeOscGameObjects();
// Start the Corotine
StartCoroutine(Oscillate(OscillationFunction.Sine, oscScalar));
}
private void InitializeOscGameObjects()
{
var objects = GameObject.FindGameObjectsWithTag("MovingObs2");
objectList = new List<OscGameObjects>();
float i = 0;
foreach (var o in objects)
{
i += waitIncrementTime;
var oscObject = new OscGameObjects();
oscObject.gameObject = o;
oscObject.startPosition = o.transform.position;
oscObject.waitCount = i;
objectList.Add(oscObject);
}
}
public IEnumerator Oscillate(OscillationFunction method, float scalar)
{
// Loop forever
while(true)
{
foreach (var element in objectList)
{
var currentPosition = element.gameObject.transform.position;
currentPosition.x = element.startPosition.x + Mathf.Cos(Time.time + element.waitCount) * scalar;
element.gameObject.transform.position = currentPosition;
}
yield return new WaitForSeconds(updateSpeed);
}
}
}
they're all difficult to contain within a desirable distance and speed from the starting position. It's too fast, and too far
Before you start monkeying with the structure of your code, I suggest you stick with the cosine function but educate yourself on the (very simple) manner in which you can manipulate output frequency and amplitude. This knowledge will serve you well (if this question is typical of your average project) and will solve the problem trivially.
If it's too fast, you can reduce the frequency (or increase the wavelength/period) by multiplying the input (which is always absolute time) by a constant coefficient between 0.0 and +1.0 (not inclusive).
If it's too far, you can reduce the amplitude by multiplying the output by a constant coefficient between 0.0 and +1.0 (not inclusive).
You just need to pick two constants and adjust to taste by running the program and seeing how you like it.

Camera doesn't smoothly interpolate its rotation

I'm facing a problem in my scene. What i'm doing is there are two panels both panel has one button which performing OnClick() listener with the method name RotateCamera().
Also in hierarchy there is a MainMenu gameobject which attached with one script. When I play the scene and click on panel one button than MainCamera rotate with 90 angle to the direction of second panel. Script works fine but I want to smoothly rotate camera to that panel when I click on that button - right now, it is rotating instantly. I don't know what I'm doing wrong on this script.
public class CameraSmooth : MonoBehaviour {
private bool check = false;
private Transform from;
private Transform to;
void Start(){
from = Camera.main.transform;
}
void Update(){
if (to != null) {
Camera.main.transform.rotation = Quaternion.Slerp (from.rotation, to.rotation, 3 * Time.deltaTime);
}
}
public void RotateCamera(){
if (!check) {
Camera.main.transform.Rotate (0,90f,0f);
to = Camera.main.transform;
check = true;
}
else if (check) {
Camera.main.transform.rotation = Quaternion.identity;
to = Camera.main.transform;
check = false;
}
}
}
The main problem here is that you're calling Camera.main.transform.Rotate() in RotateCamera(). This causes the rotation to be applied to the camera immediately, resulting in the instant rotation you're seeing.
Another small misconception - since Transform is a reference type, from and to always actually point to the same instance (the Transform of the camera)! Lastly, the value of 3 * Time.deltaTime will always average around 3/60, and will likely never end up close to 1, which is needed for an interpolation to be complete. As such, the following line:
Camera.main.transform.rotation = Quaternion.Slerp (from.rotation, to.rotation, 3 * Time.deltaTime);
will not be able to do anything even if the first issue is addressed.
The situation calls for a different solution, in my view:
Storing the target rotations in Quaternion variables rather than setting them directly on the Transform, and keeping track of the camera's initial rotation
Maintaining a timer which keeps track of the progress of the rotation (or you can abandon Slerp() and just apply an incremental rotation directly, that's also a valid approach)
Here's my suggested update to your code:
public class CameraSmooth : MonoBehaviour {
private bool check = false;
private float rotationProgress = 1;
private Quaternion initial;
private Quaternion from;
private Quaternion to;
void Start(){
// Cache the starting rotation, so we can calculate rotations relative to it
initial = Camera.main.transform.rotation;
}
void Update(){
if (rotationProgress < 1) {
rotationProgress += 3 * Time.deltaTime;
Camera.main.transform.rotation = Quaternion.Slerp (from, to, rotationProgress);
}
}
public void RotateCamera(){
from = Camera.main.transform.rotation;
rotationProgress = 0;
if (!check) {
to = initial * Quaternion.Euler(0,90f,0f);
check = true;
}
else if (check) {
to = initial;
check = false;
}
}
}
(Haven't tested this code, so please let me know if there are any issues.) Hope this helps! Let me know if you have any questions!

OnGui elements interacting with other OnGui elements

Within my 2d game i wsih to have a number of OnGui elements there for the user to select, however, the cursor that im using is another ongui element(using kinect to navigate) is this possible by any chance, at the moment im using planes but i will be zooming in and out of the camera so ill essentially need them attatched to the screen. Any ideas, suggestions or workarounds.
THis is currently my cursor.
using UnityEngine;
using System;
using System.Collections;
public class PillarAgent : MonoBehaviour {
public SkeletonWrapper sw;
public Vector3 distance;
public float progress =0f;
public Texture2D cursor;
public Texture2D load;
public Camera mainCam;
public float startTime;
private int roundedRestSecounds;
// Use this for initialization
float differencex = 0;
float differencey = 0;
void Start () {
distance =new Vector3(0f,0f,0f);
}
float translate(float value, float leftMin, float leftMax,
float rightMin,float rightMax)
{
float leftSpan = leftMax - leftMin;
float rightSpan= rightMax - rightMin;
float valueScaled = (value-leftMin)/(leftSpan);
return rightMin+(valueScaled * rightSpan);
}
// Update is called once per frame
void Update () {
if (sw.pollSkeleton())
{
distance.x=sw.bonePos[0,0].x - sw.bonePos[0,7].x;//5 is left shoulder
distance.y=sw.bonePos[0,0].y -sw.bonePos[0,7].y;
differencex=translate(distance.x,.6f,0,0,Screen.width);
differencey=translate(distance.y,-.5f,0,0,Screen.height);
//Debug.Log();
float width = sw.bonePos[0,5].x+ sw.bonePos[0,9].x;
float height =sw.bonePos[0,4].y- sw.bonePos[0,0].y;
float heightdiv= (height/2)+sw.bonePos[0,0].y;
}
}
void OnGUI() {
//left top width height
Rect r = new Rect(differencex,differencey,80,50);
GUI.Label(r,cursor);
GUI.BeginGroup(new Rect(differencex,differencey+50,50*Mathf.Clamp01(progress),15));
//Debug.Log(progress);
GUI.DrawTexture(new Rect(0,0,50,50),load);
GUI.EndGroup();
transform.position =mainCam.ScreenToWorldPoint(new Vector3(differencex,Screen.height-differencey,50));
//mainCam.fieldOfView()
}
void OnCollisionStay(Collision Other)
{
startTime+=Time.deltaTime;
if(Other.gameObject.GetComponent(typeof(TextControl)))
{
roundedRestSecounds=Mathf.CeilToInt(Time.time);
progress = Time.time *0.2f;
CurrentState=true;
}
else if(Other.gameObject.tag==("Scalpal")){
progress = startTime *0.5f;
//scallpall activated
//
}
}
void OnCollisionExit(Collision Other){
startTime =0f;
progress =0f;
}
public Boolean CurrentState{get;set;}
}
The next class is essentially the class in which i pick up my tools, currently this code doesnt work(not sure why), but what i wish to do is select some tools which show up on the screen so that i can use them,for e.g pick up paint brush start painting bricks or what not. at the moment i have my tools on a plane, i wish to always have them on the screen at all times when the camera moves.
using UnityEngine;
using System.Collections;
public class SelectTool : MonoBehaviour {
public Tools tools;
public float startTime;
public bool ScalpalSelected;
public GameObject selectedTool;
void Start()
{
tools = this.GetComponent<Tools>(); //in order to use this tools muyst be attached to the game object
//this is essentially saying with regards to this game object get the component named tools
}
void update()
{
}
void OnCollisionStay(Collision Other)
{
startTime +=Time.deltaTime;
if(startTime >5f){
if(Other.collider.tag==("Scalpal"))
{
selectedTool = Other.collider.gameObject;
Debug.Log(selectedTool+" What in gods good name is:" +tools.utilities[0]);
}
else {
selectedTool=null;
}
if(selectedTool){
for(int i=0;i<tools.utilities.Length;i++)
{
}
}
ScalpalSelected=true;
renderer.material.color = Color.yellow;
}
}
void OncollisionStay(Collision other){
startTime = 0f;
}
}
From the comment section to the question I will assume that you want to know how to do this:
"... you want your plane objects to move together with the camera ..." - Steven Mills
"thank you #StevenMills Do you have any example of how this can be done?" j bel
While the answer provided in the comments is to just manually add the planes as children of the camera (a very straightforward, manual approach), I will give another way to do this through scripting (in light of maybe this will help someone else out disregarding the likeliness of someone using this solution).
The idea of this is to create a script (thus following being attached to the MainCamera) that will search through all of the GameObject in the Object Hierarchy with the method GameObject.FindGameObjectsWithTag. Once we have all our GameObject with the associated Tag, we can then loop through the array and parent the attached script's GameObject to each.
public class ParentGameObjects : MonoBehaviour {
//The tag to search for on all game objects in the hierarchy
public String objectTag;
//The game objects that we will parent the main camera to
private GameObject[] children;
//It's not necessary to store references to the children but if you want to modify them at some point you will be able to
void Start() {
//Find all game objects with the tag we want
children = GameObject.FindGameObjectsWithTag(objectTag);
//Loop through all of the game objects found and parent this object's transform
for(int i = 0; i < children.Length; i++) {
children[i].transform.parent = transform;
}
}
}
Now, there are a few things you have to do for this script to work:
Attach this script to any GameObject that you want to parent other objects to.
In the Inspector of the GameObject that the script is attached to, enter in the name of the Tag you want to use.
For all GameObject(s) in the Hierarchy that should be added as children, assign the same Tag.
Of course there are other things you can do like, for example, instead of only searching for one Tag be able to search for multiple but that requires a bit (not exactly much) more work. Nonetheless, I hope this will at least be useful information to someone on how parenting works via scripting.

Categories