I am trying to draw a line from camera to a instantiated object.I am using the scene UnityARHitTest Example.When I touch on a vertical plane the object gets instantiated and i want to draw a line from camera to the object.When I move my device the line should show from the centre of my camera.For some reason line renderer is not showing when I call it in the Late update.
LineRenderer lins;
public GameObject Lineprefab;
bool HitTestWithResultType (ARPoint point, ARHitTestResultType resultTypes)
{
List<ARHitTestResult> hitResults = UnityARSessionNativeInterface.GetARSessionNativeInterface ().HitTest (point, resultTypes);
if (hitResults.Count > 0 && check==true)
{
foreach (var hitResult in hitResults)
{
Debug.Log ("Got hit!");
if (Select == 0)
{
Debug.Log("hit-zero!");
Instantiate(Instaobj[0], ForSelect);
check = false;
}
if (Select == 1)
{
Debug.Log("hit-one!");
Instantiate(Instaobj[1], ForSelect);
check = false;
}
if (Select == 2)
{
Debug.Log("hit-two!");
Instantiate(Instaobj[2], ForSelect);
check = false;
}
if (Select == 3)
{
Debug.Log("hit-three!");
Instantiate(Instaobj[3], ForSelect);
check = false;
}
if (Select == 4)
{
Debug.Log("hit-four!");
Instantiate(Instaobj[4], ForSelect);
check = false;
}
if (Select == 5)
{
Debug.Log("hit-five!");
Instantiate(Instaobj[5], ForSelect);
check = false;
}
m_HitTransform.position = UnityARMatrixOps.GetPosition (hitResult.worldTransform);
m_HitTransform.rotation = UnityARMatrixOps.GetRotation (hitResult.worldTransform);
Debug.Log (string.Format ("x:{0:0.######} y:{1:0.######} z:{2:0.######}", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z));
obj.StopPlaneTracking();
if (GameObject.Find("debugPlanePrefab(Clone)"))
GameObject.Find("debugPlanePrefab(Clone)").SetActive(false);
else
Debug.Log("no prefab");
//lins.SetPosition(0, m_HitTransform.position);
//lins.SetPosition(1, obj.m_camera.transform.position);
return true;
}
}
return false;
}
When I use lins.setposition() in the above method(which is commented) a line is shown in the output.When I use lins.setposition() in the below LateUpdate() the output is not shown nothing comes.
private void Start()
{
spawngenerator();
}
void spawngenerator()
{
GameObject newline = Instantiate(Lineprefab);
lins = newline.GetComponent<LineRenderer>();
//lins.SetPosition(0, m_HitTransform.position);
//lins.SetPosition(1, obj.m_camera.transform.position);
}
private void LateUpdate()
{
lins.SetPosition(0,obj.m_camera.transform.position );
lins.SetPosition(1,m_HitTransform.position );
}
Related
I have troubles trying to make two different actions on trigger enter, its same name tag so I have no idea how to do it. For example I have ground button which has function, etc on first trigger enter it is disabling rotation of some other object, on second trigger enter it enables rotation back.Tried with bools but its not working well, Im thinking about int, but Im not sure. Thanks for any help, Im new in coding.
Heres the code;
if (other.gameObject.CompareTag("Player"))
{
var buttonRenderer = button.GetComponent<Renderer>();
buttonRenderer.material.SetColor("_Color", Color.red);
Rotationplane.isRotated = false;
}
EDIT:
#derHugoDont know mate, lost my mind...but finally I managed to do it over the if statements, I have no idea does it effect the performance. Heres code if someone has the same problem. Opening the bottle of whiskey...done for today.
private void FixedUpdate()
{
if(firstCollisionDone == true)
{
firstCollisionAavaliable = false;
secondCollisionAvaliable = true;
}
if(secondCollisionDone == true)
{
secondCollisionAvaliable = false;
firstCollisionAavaliable = true;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if(firstCollisionAavaliable == true)
{
var buttonRenderer = button.GetComponent<Renderer>();
buttonRenderer.material.SetColor("_Color", Color.red);
Rotationplane.isRotated = false;
firstCollision = true;
}
if(secondCollisionAvaliable == true)
{
var buttonRenderer = button.GetComponent<Renderer>();
buttonRenderer.material.SetColor("_Color", Color.white);
Rotationplane.isRotated = true;
secondCollision = true;
}
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if(firstCollision == true)
{
firstCollisionDone = true;
firstCollision = false;
firstCollisionAavaliable = false;
secondCollisionDone = false;
}
if(secondCollision == true)
{
secondCollisionDone = true;
secondCollision = false;
secondCollisionAvaliable = false;
firstCollisionDone = false;
}
}
}
}```
I assume the flag you want to change is the Rotationplane.isRotated.
You could simply invert it's state like e.g.
if (other.gameObject.CompareTag("Player"))
{
var buttonRenderer = button.GetComponent<Renderer>();
buttonRenderer.material.SetColor("_Color", Color.red);
Rotationplane.isRotated = !Rotationplane.isRotated;
}
I have 4 buttons and each of this button activates an image (Please see the link - Stacking). One script is attached to all the 4 buttons. There are 4 placeholders. I am using an approach of stack to stack images one after another. That is, if the first slot is empty, the image goes there. The button has two functions, to add image and to remove image. If the first slot's image is removed, the second slot's image is placed on 1st slot and third slot's image is placed on 2nd slot.
How do I add push and pop to this scenario?
Edit: I tried with List but I am lost. Could there be a way simpler approach?
public class ActivateStackImages : MonoBehaviour {
public GameObject ImageGameObject_To_Add; //Each instance of this script has unique image
public Vector3[] PositionOfImages; //4 positions
private ActivateStackImages [] activateImages; //Script added to 4 buttons
public bool Slot_1_Filled = false;
public bool Slot_2_Filled = false;
public bool Slot_3_Filled = false;
public bool Slot_4_Filled = false;
public bool isImageAdded = false;
private void Awake () {
activateImages= FindObjectsOfType (typeof (ActivateStackImages )) as ActivateStackImages [];
}
public void ActivateGraph () {
if (this.isImageAdded == false) {
for (int i = 0; i < activateImages.Length; i++) {
if (activateImages[i].Slot_1_Filled == false) {
ImageGameObject_To_Add.SetActive (true);
ImageGameObject_To_Add.GetComponent<RectTransform> ().anchoredPosition = PositionOfImages[0];
activateImages[i].Slot_1_Filled = true;
} else if (activateImages[i].Slot_2_Filled == false) {
ImageGameObject_To_Add.SetActive (true);
ImageGameObject_To_Add.GetComponent<RectTransform> ().anchoredPosition = PositionOfImages[2];
activateImages[i].Slot_2_Filled = true;
} else if (activateImages[i].Slot_3_Filled == false) {
ImageGameObject_To_Add.SetActive (true);
ImageGameObject_To_Add.GetComponent<RectTransform> ().anchoredPosition = PositionOfImages[2];
activateImages[i].Slot_3_Filled = true;
} else if (activateImages[i].Slot_4_Filled == false) {
ImageGameObject_To_Add.SetActive (true);
ImageGameObject_To_Add.GetComponent<RectTransform> ().anchoredPosition = PositionOfImages[3];
activateImages[i].Slot_4_Filled = true;
}
}
this.isImageAdded = true;
} else if (this.isImageAdded == true) {
ImageGameObject_To_Add.SetActive (false);
}
}
}
Stacking
So I am trying to create this script which changes the color of the sprite when I execute the method OnMouseDown().
The color change should execute every 2 seconds. In this code provided below the colors only change once for some reason.
I have already tried coroutines. But they didn't work for some reason.
Please help thanks,
public bool startstop = false;
SpriteRenderer m_SpriteRenderer;
IEnumerator Changecolor() {
yield return new WaitForSeconds(3);
int random = Random.Range(1, 4);
if (random == 1) {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.blue;
} else if (random == 2) {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.red;
} else if (random == 3) {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.green;
} else {
this.m_SpriteRenderer = this.GetComponent<SpriteRenderer>();
this.m_SpriteRenderer.color = Color.yellow;
}
this.StartCoroutine("Changecolor", 3f);
}
private void OnMouseDown() {
if (this.startstop) {
this.StartCoroutine("Changecolor", 3f);
this.startstop = !this.startstop;
} else {
this.StopCoroutine("Changecolor");
this.startstop = !this.startstop;
}
}
No errors just doesn't work.
Do you have a Collider on the object? A Collider is needed to have the OnMouseDown event fired.
The code principally works, but is far from quality.
- Only call GetComponent() once, then cache the result. This call is very expensive.
- Initially you have to click two times, as the Coroutine will be stopped at the first click.
Here is the code with some improvements:
public bool m_isRunning = false;
public SpriteRenderer m_spriteRenderer;
private void Start() {
m_spriteRenderer = this.GetComponent<SpriteRenderer>();
}
private IEnumerator Changecolor() {
yield return new WaitForSeconds(3);
int random = Random.Range(1, 4);
if (random == 1) {
m_spriteRenderer.color = Color.blue;
} else if (random == 2) {
m_spriteRenderer.color = Color.red;
} else if (random == 3) {
m_spriteRenderer.color = Color.green;
} else {
m_spriteRenderer.color = Color.yellow;
}
this.StartCoroutine("Changecolor", 3f);
}
private void OnMouseDown() {
m_isRunning = !m_isRunning;
if (m_isRunning) {
StartCoroutine("Changecolor", 3f);
} else {
StopCoroutine("Changecolor");
}
}
Note that the second parameter you pass in (3f)
StartCoroutine ("Changecolor", 3f);
does nothing since your Changecolor does not take any arguments ...
I would actually suggest to not use Coroutine here at all but rather InvokeRepeating and CancelInvoke
void Changecolor()
{
// Either in Awake or as lazy initialization
if(!m_SpriteRenderer) m_SpriteRenderer = GetComponent<SpriteRenderer>();
int random = Random.Range(1, 4);
switch(random)
{
case 1:
m_spriteRenderer.color = Color.blue;
break;
case 2:
m_spriteRenderer.color = Color.red;
break;
case 3:
m_spriteRenderer.color = Color.green;
break;
default:
m_spriteRenderer.color = Color.yellow;
break;
}
}
private void OnMouseDown()
{
startstop = !startstop;
if (this.startstop)
{
InvokeRepeating(nameof(Changecolor), 0f, 2f);
}
else
{
CancelInvoke(nameof(Changecolor));
}
}
The code you provided works just fine, and sins you say the color changes only once, I assume you have a collider on the object that has the script attached, the only thing you should change is the continues call to GetComponent<SpriteRenderer> because it is pretty costly and should only be called in either Start or Awake another thing, which isn't major, and there is nothing wrong with it, but it kind of rubs me the wrong way, is the creation of a new coroutine at the end of the old, why not do something like this:
private Coroutine _colorChanger;
private SpriteRenderer _renderer;
void Start() //Can be Awake, whichever you choose
{
_renderer = GetComponent<SpriteRenderer>();
if (_renderer == null)
{
Debug.Log("No sprite found.");
return;
}
//This is performed if OnMouseDown is implemented, if you implement the Update with Input.GetKeyDown, then this can be removed
var collider = GetComponent<Collider>();
if (collider == null)
{
collider = gameObject.AddComponent<BoxCollider>(); //or BoxCollider2D if you are applying the script to the sprite itself.
}
collider.isTrigger = true;
}
private void OnMouseDown() //this can be swapped out for what Saif wrote, a Update method which checks if the button is down, should be GetKeyDown instead of GetKey, having it that way will eliminate the need for a collider/UI element
{
if (_colorChanger == null)
{
_colorChanger = StartCoroutine(ChangeColor(2f));
}
else
{
StopCoroutine(_colorChanger);
_colorChanger = null;
}
}
IEnumerator ChangeColor(float timeoutSec)
{
while (true)
{
yield return new WaitForSeconds(timeoutSec);
int random = Random.Range(1, 5); //Change max from 4 to 5
if (random == 1)
{
_renderer.color = Color.blue;
}
else if (random == 2)
{
_renderer.color = Color.red;
}
else if (random == 3)
{
_renderer.color = Color.green;
}
else
{
_renderer.color = Color.yellow;
}
}
}
Update: just noticed something that others missed, you should change the Random.Range(1, 4) to Random.Range(1, 5) or else the yellow color will never come into effect.
Your code is right, no issues in it except that the OnMouseDown() function will not be called since you are not clicking on any box triggers or any UI elements. Hence try to use update function as given below:
void Update()
{
if (Input.GetKey(KeyCode.Mouse0))
{
if (startstop == false)
{
StartCoroutine("Changecolor", 3f);
this.startstop = !this.startstop;
}
else
{
StopCoroutine("Changecolor");
this.startstop = !this.startstop;
}
}
}
I'm working on a small game where objects are put in a boat, then a key press makes the boat "sail".
To move all the objects that are standing on the boat, i am setting the parent of each object to an empty guide object in the boat then changing the position of the boat. (I have also tried parenting the objects into the boat object itself)
The following is a script applied to the boat object.
variables set in the BoatScript class:
public class BoatScript : MonoBehaviour {
public List<string> boatList;
public KeyCode interact;
public GameObject tempObject;
public string whichSide;
public string direction;
public bool canSail;
}
Start and Update method:
void Start () {
canSail = false;
whichSide = "start";
direction = "toFinish";
speed = 0f;
}
void Update () {
if (canSail == true)
{
SetSail();
}
if (boatList.Contains("FARMER") && whichSide == "start" && Input.GetKeyDown(interact))
{
speed = 0.5f;
CharacterCheck();
}
else if (boatList.Contains("FARMER") && whichSide == "finish" && Input.GetKeyDown(interact))
{
speed = -0.05f;
CharacterCheck();
}
}
Here are my OnTrigger methods:
void OnTriggerEnter(Collider other)
{
Debug.Log(other.gameObject.name + " collided with " + gameObject.name);
promptText.text = "";
if(CheckValidObject(other.gameObject.name) == true) {
boatList.Add(other.gameObject.name);
logBox.text = logBox.text + "\nThe " + other.gameObject.name + " is in the boat";
}
if (other.gameObject.name == "FARMER")
{
promptText2.text = "Press E to set sail";
}
}
void OnTriggerExit(Collider other)
{
boatList.Remove(other.gameObject.name);
logBox.text = logBox.text + "\nThe " + other.gameObject.name + " has left the boat";
promptText.text = "";
if (other.gameObject.name == "FARMER")
{
promptText2.text = "";
}
}
Setting sail:
void SetSail()
{
promptText.text = "";
promptText2.text = "";
addParents();
if (whichSide == "sailing" && direction == "toFinish")
{
speed = 0.05f;
gameObject.transform.Translate(speed, 0, 0);
}
else if (whichSide == "sailing" && direction == "toStart")
{
speed = -0.05f;
gameObject.transform.Translate(speed, 0, 0);
}
else if (whichSide == "start" || whichSide == "finish")
{
gameObject.transform.Translate(speed, 0, 0);
removeParents();
}
}
void addParents()
{
foreach(string o in boatList)
{
GameObject obj = GameObject.Find(o);
obj.GetComponent<Rigidbody>().useGravity = false;
obj.GetComponent<Rigidbody>().isKinematic = true;
if (obj.name == "FARMER") { obj.transform.parent = playerGuide.transform; }
else {obj.transform.parent = itemGuide.transform; }
}
}
void removeParents()
{
foreach (string o in boatList)
{
GameObject obj = GameObject.Find(o);
obj.GetComponent<Rigidbody>().useGravity = true;
if(obj.name != "FARMER") {obj.GetComponent<Rigidbody>().isKinematic = false; }
obj.transform.parent = null;
}
}
The problem: Once the boat reaches and hits the collider for the other side, the boat stops as expected but the objects that were just removed from the parent begin to scale up continuously like this:
e.g 1 https://i.gyazo.com/d35ae729757b8e71c25fd1b4a3857dae.mp4
e.g 2 https://i.gyazo.com/80637919bfd114a42d187300b7faef25.mp4
I'm not too sure what is causing this. Any help is much appreciated, thank you.
Instead of setting the parent via transform.parent, use transform.SetParent(targetTransform, false);. The second, bool, parameter determines if the game object's transform will maintain it's position, orientation, and scale. By setting it to false, the transform will maintain it's current values, while setting it to true will modify the position, orientation, and scale to maintain the world position. You can check this for further info transform.SetParent
Are youu sure it is scaling up and not moving up in the Z axes? From what im looking it is going towards the camera but not scaling up. You should debug the position and scale in the update method to see whats really happening there.
Below comment: "Well then you will have to debug it more carefully, i would first try, setting canSail to false as soon as it reaches the end. Perhaps the method addParent which is always being executed is wrong, what does the object itemGuide does? edit: i just seen the second video, from my perspective that seems gravity, what you meant with problems with scaling up is because its moving out from the boat?"
Solution:
void SetSail()
{
promptText.text = "";
promptText2.text = "";
addParents();
if (whichSide == "sailing" && direction == "toFinish")
{
speed = 0.05f;
gameObject.transform.Translate(speed, 0, 0);
}
else if (whichSide == "sailing" && direction == "toStart")
{
speed = -0.05f;
gameObject.transform.Translate(speed, 0, 0);
}
else if (whichSide == "start" || whichSide == "finish")
{
gameObject.transform.Translate(speed, 0, 0);
canSail = false; //Adding this line solves the issues, must have been affecting transform properties to child objects.
removeParents();
}
}
Basically, I need a script to play a walking-sound while my player is walking and a running-sound while he's running. Due to how my player is setup it needs to be done with the Input and Keys...
I have this basic script made but it doesn't work too well. The transition from running -> walking -> stop and running -> stop and so on doesn't work consistently or even well. The other problem is pressing shift while standing still also plays the sound. I already tried doing the SHIFT && W || W && SHIFT and it just doesn't work.
Any help would be much appreciated!!
My Foley.cs script:
using UnityEngine;
using System.Collections;
public class Foley : MonoBehaviour {
public AudioClip Footsteps;
public AudioClip RunningSound;
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.LeftShift) && !audio.isPlaying)
{
audio.clip = RunningSound;
audio.loop = true;
audio.Play();
} else if (Input.GetKey(KeyCode.W) && !audio.isPlaying && !Input.GetKey(KeyCode.LeftShift)) {
audio.clip = Footsteps;
audio.loop = true;
audio.Play();
}
if (Input.GetKeyUp(KeyCode.W) && audio.isPlaying)
{
audio.Stop();
}
if (Input.GetKeyUp(KeyCode.LeftShift) && audio.isPlaying)
{
if (Input.GetKey(KeyCode.W))
{
audio.clip = Footsteps;
audio.loop = true;
audio.Play();
} else {
audio.Stop();
}
}
}
}
This script should do basically what you want. On 'w' play walk sound, on w + shift, play run sound.
#pragma strict
var walk : AudioClip;
var run : AudioClip;
var isWalking : boolean = false;
var isRunning : boolean = false;
function Update()
{
GetState();
PlayAudio();
}
function GetState()
{
if ( Input.GetKey(KeyCode.W))
{
if ( Input.GetKey( "left shift" ) || Input.GetKey( "right shift" ) )
{
// Running
isWalking = false;
isRunning = true;
}
else
{
// Walking
isWalking = true;
isRunning = false;
}
}
else
{
// Stopped
isWalking = false;
isRunning = false;
}
}
function PlayAudio()
{
if ( isWalking )
{
if ( audio.clip != walk )
{
audio.Stop();
audio.clip = walk;
}
if ( !audio.isPlaying )
{
audio.Play();
}
}
else if ( isRunning )
{
if ( audio.clip != run )
{
audio.Stop();
audio.clip = run;
}
if ( !audio.isPlaying )
{
audio.Play();
}
}
else
{
audio.Stop();
}
}