On startup the flashlight toggle script mode toggles ON/OFF, I'm not sure how to patch this.
I believe it's coming from IEnumerator Start() but, I've tried changing the yield return new WaitForSeconds to 0 but that didn't change a thing.
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using Vuforia;
public class FlashlightAPI : MonoBehaviour
{
IEnumerator Start()
{
yield return new WaitForSeconds(0);
hasTorch = CameraDevice.Instance.SetFlashTorchMode(true);
yield return new WaitForSeconds(0.000f);
CameraDevice.Instance.SetFlashTorchMode(false);
}
bool torchState = true, hasTouch = false;
public bool hasTorch;
public FlashlightAPI(bool torchState, bool hasTorch)
{
this.torchState = torchState;
this.hasTorch = hasTorch;
}
}
Zero is too long
Wait makes Unity wait until the next frame after the condition has passed. In this case, it waits for the first frame after at least 0 seconds have elapsed, meaning that it waits 1 frame.
If you want it to happen instantly, you need to remove the Waits entirely.
void Start()
{
hasTorch = CameraDevice.Instance.SetFlashTorchMode(true);
CameraDevice.Instance.SetFlashTorchMode(false);
}
However as you're fiddling with an external device (the phone's camera), this may still cause the light to flash and you should refer to the documentation to resolve the issue. As CameraDevice is not a Unity class I cannot do this for you.
Related
I am using ARKit within Unity to implement face tracking on an iOS device. Face tracking is working fine, and I want to access the real-time centerEyeRotation measurements produced by the face tracking. Following this helpful post
I used the code below to try and at least access the TrackedPoseDriver, but I keep getting back the data from the Main Camera (the game object that this script is attached to). Any idea how I can access the centerEyeRotation data?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class getTrackedPoseDriver : MonoBehaviour
{
bool found;
MonoBehaviour mbTrackingPose;
MonoBehaviour mb;
// Start is called before the first frame update
void Start()
{
Component[] components = Camera.main.GetComponents(typeof(MonoBehaviour));
found = false;
foreach (Component component in components)
{
string name = component.ToString();
mb = (MonoBehaviour)component;
if (name.Contains("UnityEngine.InputSystem.XR.TrackedPoseDriver"))
{
mbTrackingPose = mb;
found = true;
Debug.Log(found);
Debug.Log(mbTrackingPose.name);
break;
}
}
}
// Update is called once per frame
void Update()
{
Debug.Log(mbTrackingPose.transform.rotation.y);
}
}
I also attempted a different approach (see below). This script (attached to the Main Camera) does confirm XRNode.CenterEye as valid, but device.TryGetFeatureValue fails to get centerEyePosition.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class centerEyeRotation : MonoBehaviour
{
Quaternion centEyeRot;
Vector3 centEyePos;
//Quaternion rotation;
bool tryGet;
// Start is called before the first frame update
void Start()
{
tryGet = false;
InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye);
if (device.isValid)
{
Debug.Log("Device is valid");
if (device.TryGetFeatureValue(CommonUsages.centerEyePosition, out centEyePos))
tryGet = true;
Debug.Log("centerEyePosition found");
}
}
}
I may have solved the problem via a different route; the project instantiates an AR face prefab object at runtime. By attaching a script to this prefab I was able to report the transform of the prefab, which seems to be giving me the orientation data I need.
This question already has answers here:
How to make the script wait/sleep in a simple way in unity
(7 answers)
Closed 4 months ago.
I'm a new C# programmer here in the early stages of creating a project in Unity where you play as a microbe that needs to eat blue food pellets to grow and survive. I've got the blue food pellets to spawn randomly across the map but I want to add a delay because too much is spawning at once. This is what I've attempted to do so far. Any help would be appreciated!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
public class Spawner : MonoBehaviour
{
public GameObject food;
public async void Wait(float duration)
{
Vector3 randomSpawnPosition = new Vector3(Random.Range(-50, 50), 1, Random.Range(-50, 50));
Instantiate(food, randomSpawnPosition, Quaternion.identity);
await Task.Delay((int)duration * 1000);
}
// Update is called once per frame
void Update()
{
async void Wait(float duration);
}
}
What I've tried:
Putting the delay function in the update function. The program just gets confused and thinks I'm trying to call the function.
Calling the function after combining all my code into the one function, the program rejects this.
Like the default code snippet says, Update runs every frame. Using Task.Delay to delay events would still spawn objects with the same frequency, they would only start spawning delayed.
The typical way to do this in Unity is to use a coroutine.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField] GameObject food;
protected void OnEnable()
{
StartCoroutine(SpawnFoodRoutine());
}
IEnumerator SpawnFoodRoutine()
{
while(enabled)
{
SpawnFood();
var waitTime = Random.Range(1f, 5f);
yield return new WaitForSeconds(waitTime);
}
}
void SpawnFood()
{
Vector3 randomSpawnPosition = new Vector3(
Random.Range(-50f, 50f),
1f,
Random.Range(-50f, 50f));
Instantiate(food, randomSpawnPosition, Quaternion.identity);
}
}
I have made this prefab called “pellet”, then I have created a new gameObject called “SpawnManager” and, finally, added this script to SpawnManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnPellet : MonoBehaviour
{
public GameObject prefab;
public bool canSpawnNewPellet = true;
public float delay;
void Update(){
if(canSpawnNewPellet){
Invoke("SpawnNewPellet", delay);
canSpawnNewPellet = false;
}
}
void SpawnNewPellet()
{
GameObject instance = Instantiate(prefab);
instance.transform.position = new Vector3(Random.Range(0,10), Random.Range(0,10), 0);
canSpawnNewPellet = true;
}
}
The I have dragged and dropped/edited values on the fields in the inspector (Prefab, canSpawnNewPellet and Delay). Those are public fields inside the script, so you can populate them drag and dropping directly from your assets folder.
Hit play and you have a new spawn every X seconds where X is the value of delay in seconds.
Screenshot of the game executing after 21 seconds.
What does it do?
Every frame it evaluates if can spawn a new pellet (bool canSpawnNewPellet). If it can, then it starts an invocation of another method with X seconds (and mark the bool as false since we don’t want to call more invocations during de instantiation of our first sample).
For more references: https://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html
Edited: typo.
I'm totally newbie in Unity and C#, and will apprecaite your Help.
i'm trying to make tower Defense Game,with help of Tutorial, but it seems to be a Problem with while under my Game Loop,it will freez each time i use While. and something else that i notice is EnemyIDsToSummon.Count is whole the time 0.
here you can see my GameLoop:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameLoopManager : MonoBehaviour
{
private static Queue<int> EnemyIDsToSummon;
public bool LoopShouldEnd;
private void Start()
{
EnemyIDsToSummon= new Queue<int>();
EntitySummoner.Init();
StartCoroutine(GameLoop());
InvokeRepeating("SummonTest", 0f, 1f);
}
void SummonTest(){
EnqueueEnemyIDToSummon(1);
}
IEnumerator GameLoop(){
while(LoopShouldEnd==false){
//Spawn Enemies
if(EnemyIDsToSummon.Count>0)
{
for(int i=0;i<EnemyIDsToSummon.Count;i++){
EntitySummoner.SummonEnemy(EnemyIDsToSummon.Dequeue());
}
}
//Spawn Towers
//Move Enemies
//Tick Towers
//Apply Effects
//Damge Enemies
//Remove Enemies
// remove Towers
}
yield return null;
}
public static void EnqueueEnemyIDToSummon(int ID){
EnemyIDsToSummon.Enqueue(ID);
}
}
and here is the tutorial i've used:
https://www.youtube.com/watch?v=-Pj5o5I_Wl4&t=1263s
You've written a Unity coroutine GameLoop, which has a while loop in it.
The engine will enter the while loop and never leave, because nothing sets LoopShouldEnd to true, or breaks out of the loop.
Usually, you'd fix this by yielding from the coroutine (yield return null) from inside the while loop, and setting LoopShouldEnd to false on the frame you want it to stop, or ending the while loop once you're done spawning inside that frame (you can break to end it immediately)
When the yield is outside the while loop, it will only happen after the while loop finishes, which is never, so no other code runs and the editor freezes.
Some useful documentation on coroutines:
https://docs.unity3d.com/Manual/Coroutines.html
As the title states the animation is not playing. the line telling it to play is in a coroutine and the code is before a waitforseconds(3f).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Play : MonoBehaviour {
public Animator AnimatorRef;
// Use this for initialization
void Start () {
if (AnimatorRef == null)
{
AnimatorRef = GetComponent<Animator>();
}
}
public void PlayGame()
{
StartCoroutine(TitlePlay());
Debug.Log("playing");
}
IEnumerator TitlePlay()
{
Debug.Log("playing1");
AnimatorRef.SetBool("Enlarge", true);
yield return new WaitForSeconds(3f);
Debug.Log("playing2");
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
it grabs the animator reference fine and all three of the comments show.
2 Considerations.
1st -
Did you check your transitions and AnimationController?
You can open up the AnimationController to see if the bool changes during runtime, if it does you'll know there is a transition error somewhere between your animation states.
2nd -
If you comment out the "LoadScene" part, does the animation then play correctly?
I suspect that the Animation bool is for some reason not allowed to carry out it's actions before the entire method has been run through, could be wrong though.
My unity shutdown without saving but it now works. If anyone has this problem remake the animation and MAKE SURE you go from the initial animation and click add clip. Then it worked for me :)
How can I create a flashing object in Unity using SetActiveRecursively (Moment = 1 second).
My example (for changes):
public GameObject flashing_Label;
private float timer;
void Update()
{
while(true)
{
flashing_Label.SetActiveRecursively(true);
timer = Time.deltaTime;
if(timer > 1)
{
flashing_Label.SetActiveRecursively(false);
timer = 0;
}
}
}
Use InvokeRepeating:
public GameObject flashing_Label;
public float interval;
void Start()
{
InvokeRepeating("FlashLabel", 0, interval);
}
void FlashLabel()
{
if(flashing_Label.activeSelf)
flashing_Label.SetActive(false);
else
flashing_Label.SetActive(true);
}
Take a look on unity WaitForSeconds function.
By passing int param. (seconds), you can toggle your gameObject.
bool fadeIn = true;
IEnumerator Toggler()
{
yield return new WaitForSeconds(1);
fadeIn = !fadeIn;
}
then call this function by StartCoroutine(Toggler()).
You can use the Coroutines and new Unity 4.6 GUI to achieve this very easily. Check this article here which falsges a Text. YOu can modify it easily for gameobject easily
Blinking Text - TGC
If you just need the code, here you go
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class FlashingTextScript : MonoBehaviour {
Text flashingText;
void Start(){
//get the Text component
flashingText = GetComponent<Text>();
//Call coroutine BlinkText on Start
StartCoroutine(BlinkText());
}
//function to blink the text
public IEnumerator BlinkText(){
//blink it forever. You can set a terminating condition depending upon your requirement
while(true){
//set the Text's text to blank
flashingText.text= "";
//display blank text for 0.5 seconds
yield return new WaitForSeconds(.5f);
//display “I AM FLASHING TEXT” for the next 0.5 seconds
flashingText.text= "I AM FLASHING TEXT!";
yield return new WaitForSeconds(.5f);
}
}
}
P.S: Even though it seems to be an infinite loop which is generally considered as a bad programming practice, in this case it works quite well as the MonoBehaviour will be destroyed once the object is destroyed. Also, if you dont need it to flash forever, you can add a terminating condition based on your requirements.
Simple way is to use InvokeRepeating() and CancelInvoke() method.
InvokeRepeating("BlinkText",0,0.3) will repeatedly call BlinkText() for every 0.03 time Interval.
CancelInvoke("BlinkText") will stop the repeating invoke.
Here's the example :
//Call this when you want to start blinking
InvokeRepeating("BlinkText", 0 , 0.03f);
void BlinkText() {
if(Title.gameObject.activeSelf)
Title.gameObject.SetActive(false);
else
Title.gameObject.SetActive(true);
}
//Call this when you want to stop blinking
CancelInvoke("BlinkText");
Unity Documentation