Hello in my below code i am updating my camera position using UI Buttons which is working fine what i want is to do this same process but by pressing right arrow key like if i press right arrow key camera will change its position to point A then stops there and when again i press the same arrow key the camera will change its position to point B and as in the code i have a different function to be called on different ui button so on thanks here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cam : MonoBehaviour
{
[Header("Locations where camera will update its position step by step")]
public Transform handleview;
public Transform needle1view;
public Transform wallview;
public Transform handletwoview;
public Transform needle2view;
public Transform switchview;
public Transform lastswitchview;
public GameObject Animatebtn;
Animator animatebtnanim;
[Header("UI Buttons")]
public GameObject inspectionbtn;
public GameObject animatebtn;
public GameObject step2btn;
public GameObject step3btn;
public GameObject step4btn;
public GameObject step5btn;
public GameObject step6btn;
public GameObject step7btn;
[Header("Inspection Views")]
public Transform startview;
public Transform handle1view;
public Transform motorview;
public Transform handle2view;
[Header("Move Boolean")]
public bool move = false;
[Header("Speed At Which Cam Moves")]
public float speed;
[Header("Current View/position Of Camera")]
Transform currentVIEW;
[Header("Current Angel Of Camera")]
Vector3 currentangel;
[Header("FieldofView of Camera ")]
public float camFieldOFview = 24f;
public int track = 0;
// Use this for initialization
void Start()
{
Camera.main.fieldOfView = camFieldOFview;
animatebtnanim = Animatebtn.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (move)
{
//float step = speed * Time.deltaTime;
//transform.position = Vector3.MoveTowards(transform.position, currentVIEW.position, step);
transform.position = Vector3.Lerp(transform.position, currentVIEW.position, Time.deltaTime * speed);
currentangel = new Vector3(Mathf.LerpAngle(transform.rotation.eulerAngles.x, currentVIEW.transform.rotation.eulerAngles.x, Time.deltaTime * speed),
Mathf.LerpAngle(transform.rotation.eulerAngles.y, currentVIEW.transform.rotation.eulerAngles.y, Time.deltaTime * speed),
Mathf.LerpAngle(transform.rotation.eulerAngles.z, currentVIEW.transform.rotation.eulerAngles.z, Time.deltaTime * speed));
transform.eulerAngles = currentangel;
}
//if (Input.GetKey(KeyCode.RightArrow))
//{
// if (track == 7)
// track = 1;
// if (track == 1)
// {
// moveTOstartVIEW();
// move = true;
// }
// else if (track == 2)
// {
// moveTOhandleONEview();
// move = true;
// }
// track += 1;
//}
}
// this function will lerp camera to startview location
public void moveTOstartVIEW()
{
currentVIEW = startview;
move = true;
}
public void moveTOhandleONEview()
{
currentVIEW = handle1view;
move = true;
animatebtnanim.SetBool("start", true);
animatebtnanim.SetBool("move", false);
}
public void moveTOmotorview()
{
currentVIEW = motorview;
move = true;
}
public void moveTOhandleTWOview()
{
currentVIEW = handle2view;
move = true;
}
public void Handleview()
{
currentVIEW = handleview;
inspectionbtn.SetActive(false);
animatebtn.SetActive(false);
move = true;
}
public void Needleoneview()
{
currentVIEW = needle1view;
step2btn.SetActive(false);
move = true;
}
public void Wallview()
{
currentVIEW = wallview;
move = true;
step3btn.SetActive(false);
}
public void Handletwoview()
{
currentVIEW = handletwoview;
move = true;
step4btn.SetActive(false);
}
public void Needletwoview()
{
currentVIEW = needle2view;
move = true;
step5btn.SetActive(false);
}
public void Switchview()
{
currentVIEW = switchview;
move = true;
step6btn.SetActive(false);
}
public void lastSwitchview()
{
currentVIEW = lastswitchview;
move = true;
step7btn.SetActive(false);
}
}
As I understood you have a usual UI.Button component and now want to do the same thing on a certain keyboard key as this button would do in onClick.
Solution 1: Extending the Button
I would simply invoke the Button's onClick event after getting a certain KeyCode by putting the following component right next to the Button component on your button objects (not on the camera)
using UnityEngine;
// make sure you are not accidentely using
// UnityEngine.Experimental.UIElements.Button
using UnityEngine.UI;
[RequireComponent(typeof(Button))]
public class KeyboardButton : MonoBehaviour
{
// Which key should this Button react to?
// Select this in the inspector for each Button
public KeyCode ReactToKey;
private Button _button;
private void Awake()
{
_button = GetComponent<Button>();
}
// Wait for the defined key
private void Update()
{
// If key not pressed do nothing
if (!Input.GetKeyDown(ReactToKey)) return;
// This simply tells the button to execute it's onClick event
// So it does exactly the same as if you would have clicked it in the UI
_button.onClick.Invoke();
}
}
Solution 2: Replacing the Button
Alternatively if you do not want to use a Button anymore at all you can add your own UnityEvent e.g. OnPress to the above script instead
using UnityEngine;
using UnityEngine.Events;
public class KeyboardButton : MonoBehaviour
{
// Which key should this Button react to?
// Select this in the inspector for each Button
public KeyCode ReactToKey;
// reference the target methods here just as
// you would do with the Button's onClick
public UnityEvent OnPress;
// Wait for the defined key
private void Update()
{
// If key not pressed do nothing
if (!Input.GetKeyDown(ReactToKey)) return;
OnPress.Invoke();
}
}
Related
I have a rebind script in my game that looks like this:
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.EventSystems;
using TMPro;
public class RebindButton : MonoBehaviour
{
[SerializeField] private InputActionReference inputActionRef;
[SerializeField] private TMP_Text buttonText;
[SerializeField] private int actionIndex = 0;
private InputActionRebindingExtensions.RebindingOperation rebindingOperation;
private void Start()
{
buttonText.text = InputControlPath.ToHumanReadableString(inputActionRef.action.bindings[actionIndex].effectivePath,
InputControlPath.HumanReadableStringOptions.OmitDevice);
}
public void StartRebinding()
{
if (inputActionRef.action.bindings[actionIndex].isPartOfComposite)
{
Debug.Log(inputActionRef.action.bindings[actionIndex].path);
}
rebindingOperation = inputActionRef.action.PerformInteractiveRebinding(actionIndex)
.WithCancelingThrough("<Keyboard>/escape")
.OnMatchWaitForAnother(0.1f)
.OnCancel(operation => RebindCancel())
.OnComplete(operation => RebindComplete())
.Start();
}
private void RebindComplete()
{
Debug.Log(inputActionRef.action.bindings[actionIndex].path);
buttonText.text = InputControlPath.ToHumanReadableString(inputActionRef.action.bindings[actionIndex].effectivePath,
InputControlPath.HumanReadableStringOptions.OmitDevice);
rebindingOperation.Dispose();
FindObjectOfType<EventSystem>().SetSelectedGameObject(null);
}
private void RebindCancel()
{
rebindingOperation.Dispose();
FindObjectOfType<EventSystem>().SetSelectedGameObject(null);
}
}
But all bindings that I change keep the same action path as before, even though their inputaction.callback button changing according to rebinding. That makes impossible to change my composite Vector2 movement binding. Vector2 changing only when I press button that showed in the action path. My movements set to WASD. When I changing it to the arrows my hero starting to move only when I press one of the arrows and one of WASD buttons. His direction changes according to the WASD buttons I press. Here is some movement script code:
void Update()
{
if (moveButtonIsHeld)
{
direction = playerInput.PlayerMovement.Movement.ReadValue<Vector2>();
areTwoKeysPressed = direction.x != 0 && direction.y != 0;
Move();
}
else
playerComponent.animator.SetLayerWeight(1, 0);
}
public void SetStateMoveButton(InputAction.CallbackContext context)
{
if (context.performed)
moveButtonIsHeld = true;
if (context.canceled)
moveButtonIsHeld = false;
}
public void Move()
{
transform.Translate(direction * speed * Time.deltaTime);
if (direction.x != 0 || direction.y != 0)
SetAnimatorMovement(direction);
}
Also I would like to ask how to get actionIndex in the script. Now I'm setting it manually in the inspector.
I'm new to unity, and I'm trying to build a menu to a game, but I can't seem to be able to use a key press to activate the button.
public class MenuCamControl : MonoBehaviour
{
public Transform currentMount;
public float speed = 0.1f;
public float zoom = 0.1f;
void Update()
{
transform.position = Vector3.Lerp(transform.position, currentMount.position, speed);
transform.rotation = Quaternion.Slerp(transform.rotation, currentMount.rotation, speed);
}
public void SetMount(Transform newMonut)
{
currentMount = newMonut;
}
}
Edit: I added the code I have right now, which is a animation.
Edit2: This is where the animation leads image
Use Input.anyKey and a flag to determine when the first key is pressed to not trigger it multiple times.
public class Example: MonoBehaviour
{
private bool keyPressed = false;
void Update()
{
if (Input.anyKey && !keyPressed)
{
keyPressed = true;
}
else
{
// put your camera move code here
}
}
}
This method also picks up any mouse input as well. If you truly just want any keyboard input and not any mouse input to continue I can update my answer.
You do not need a UI button for this. Just a function to track if an input occurs and another to handle starting or loading your game. If you want the game to start when a button is clicked, you would just need to assign the onClick listener to a function either in code or in the inspector.
If you add what code you'd like to run or what you'd like to do after the click I can update my snippet.
Edit: Here is how you would combine my snippet and your current code. You can also use a Coroutine, but it is not needed.
public class MenuCamControl : MonoBehaviour
{
public Transform currentMount;
public float speed = 0.1f;
public float zoom = 0.1f;
private bool keyPressed = false;
void Update()
{
if (Input.anyKey && !keyPressed)
{
keyPressed = true;
}
else
{
transform.position = Vector3.Lerp(transform.position, currentMount.position, speed);
transform.rotation = Quaternion.Slerp(transform.rotation, currentMount.rotation, speed);
}
}
// I am not sure what this does, it currently is not called?
public void SetMount(Transform newMonut)
{
currentMount = newMonut;
}
}
With a Coroutine, it could look something like
void Update()
{
if (Input.anyKey && !keyPressed)
{
keyPressed = true;
if(referenceToCoroutine == null)
referenceToCoroutine = StartCoroutine(DoCameraAnimation());
}
}
private IEnumerator DoCameraAnimation()
{
...
}
You would need to change your current camera animation slightly to work in a Coroutine.
When Character is arrived destination, I want to get callback.
However I don't want to write into Update Function.
If I've get to write into Update, I want to write smartly and elegant code.
when we make game, if there is design pattern.
Let me teach about it.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Unit : MonoBehaviour
{
[SerializeField] Vector3 targetPosition;
private NavMeshAgent agent;
private bool arrived;
private Transform myPosition;
void Start()
{
myPosition = GetComponent<Transform>();
agent = GetComponent<NavMeshAgent>();
agent.updateRotation = false;
agent.updateUpAxis = false;
}
void Update()
{
agent.SetDestination(targetPosition);
}
public void MoveTo(Vector3 position, float stopDistance, Action onArrivedAtPosition)
{
targetPosition = position;
// here!
if (arrived)
{
onArrivedAtPosition();
}
}
private void IsArrived()
{
if (Vector3.Distance(myPosition.position, agent.destination) < 1.0f)
{
arrived = true;
}
arrived = false;
}
}
I would use a Coroutine. Coroutines are like small temporary Update routines but easier to control and maintain.
private Coroutine _currentRoutine;
private bool IsArrived()
{
// Instead of setting a field directly return the value
return Vector3.Distance(myPosition.position, agent.destination) < 1.0f;
}
public void MoveTo(Vector3 position, float stopDistance, Action onArrivedAtPosition)
{
// Here can/have to decide
// Either Option A
// do not allow a new move call if there is already one running
if(_currentRoutine != null) return;
// OR Option B
// interrupt the current routine and start a new one
if(_currentRoutine != null) StopCoroutine (_currentRoutine);
// Set the destination directly
agent.SetDestination(position);
// and start a new routine
_currentRoutine = StartCoroutine (WaitUntilArivedPosition(position, onArrivedAtPosition));
}
private IEnumerator WaitUntilArivedPosition (Vector3 position)
{
// yield return tells Unity "pause the routine here,
// render this frame and continue from here in the next frame"
// WaitWhile does what the name suggests
// waits until the given condition is true
yield return new WaitUntil (IsArrived);
_currentRoutine = null;
onArrivedAtPosition?.Invoke();
}
You could create a script like the one bellow and attach it to an empty gameobject, then place that empty gameobject at target position. Make sure your IsArrived method (in Unit script) is public and also assign the unit on the empty gameobjec's TargetPoint script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TargetPoint : MonoBehaviour
{
public float radius = 1f;
public Unit unit = null;
private bool called = false;
private void Start()
{
SphereCollider c = gameObject.AddComponent<SphereCollider>();
c.radius = radius;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawSphere(transform.position, radius);
}
private void OnTriggerEnter(Collider other)
{
if (called)
{
return;
}
if(other.transform == unit.transform)
{
unit.IsArrived();
called = true;
}
}
}
This is what I tried but the text is never show on the text mesh :
SecurityKeypadKeys script :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
public class SecurityKeypadKeys : MonoBehaviour
{
// I would rather go this way round
// Configure the number for each key via the Inspector
// they will then set their own names for debugging
// I wouldn't the other way round rely on that the names are correct
[SerializeField] private int _number;
// Here you can attach callback handlers that will be executed
// For each time this key is pressed
public event Action<int> onKeyPressed;
private void Awake()
{
name = $"Key {_number}";
}
private void OnMouseDown()
{
// This class is only responsible for invoking its event
// It doesn't know and has no authority over how many digits are allowed in the display etc
// it doesn't even know a display exists or that the values get stored by someone
onKeyPressed?.Invoke(_number);
}
}
The SecurityKeypadSystem script :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SecurityKeypadSystem : MonoBehaviour
{
[Header("References")]
// rather let this class control the display text
[SerializeField] private TextMesh _text;
[Header("Settings")]
// also rather let this class control the length of a code
[SerializeField] private int _codeLength = 8;
[Header("Debugging")]
[SerializeField] private GameObject[] _keyPadNumbers;
[SerializeField] private List<int> _code = new List<int>();
// This will be invoked once the code length has reached the target length
public event Action<int> OnCodeComplete;
// Start is called before the first frame update
private void Start()
{
_keyPadNumbers = GameObject.FindGameObjectsWithTag("Keypad");
// register a callback to each key that handles the numbers
foreach (var keyPadNumber in _keyPadNumbers)
{
// It is save to remove an event even if it hasn't been added yet
// this makes sure it is only added exactly once
// only adding this here for the case you later have to move this again to Update for some reason ;)
var securityKeypadKeys = keyPadNumber.GetComponent<SecurityKeypadKeys>();
securityKeypadKeys.onKeyPressed -= HandleKeyPressed;
securityKeypadKeys.onKeyPressed += HandleKeyPressed;
}
}
private void OnDestroy()
{
// just for completeness you should always remove callbacks as soon as they are not needed anymore
// in order to avoid any exceptions
foreach (var keyPadNumber in _keyPadNumbers)
{
var securityKeypadKeys = keyPadNumber.GetComponent<SecurityKeypadKeys>();
securityKeypadKeys.onKeyPressed -= HandleKeyPressed;
}
}
// this is called when a keypad key was pressed
private void HandleKeyPressed(int value)
{
// add the value to the list
_code.Add(value);
_text.text += value.ToString();
// Check if the code has reached the target length
// if not do nothing
if (_code.Count < _codeLength) return;
// if it reached the length combine all numbers into one int
var exponent = _code.Count;
float finalCode = 0;
foreach (var digit in _code)
{
finalCode =digit * Mathf.Pow(10, exponent);
exponent--;
}
// invoke the callback event
OnCodeComplete?.Invoke((int)finalCode);
// and reset the code
ResetCode();
}
// Maybe you later want an option to clear the code field from the outside as well
public void ResetCode()
{
_code.Clear();
_text.text = "";
}
// also clear the input if this gets disabled
private void OnDisable()
{
ResetCode();
}
}
Last the UnlockCrate script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class UnlockCrate : MonoBehaviour
{
[Header("Settings")]
[SerializeField] private int _targetCode;
public GameObject securityKeyPad;
public GameObject player;
public Animation anim;
public IKControl ikControl;
public InteractableItem interactableItem;
public CinemachineVirtualCamera virtualCam;
public CinemachineFreeLook freeLookCam;
public CamerasControl camerasContorl;
private bool playAnimOnce = false;
[SerializeField] private SecurityKeypadSystem securityKeypadSystem;
private void Start()
{
// as before attach a handler that is triggered once the system completes one code
securityKeypadSystem.OnCodeComplete -= HandleInputCode;
securityKeypadSystem.OnCodeComplete += HandleInputCode;
}
private void OnDestroy()
{
securityKeypadSystem.OnCodeComplete -= HandleInputCode;
}
private void Update()
{
var distance = Vector3.Distance(player.transform.position, transform.position);
if (distance <= interactableItem.distance)
{
if (!playAnimOnce)
{
if (ikControl.handFinishedMove == true)
{
securityKeyPad.SetActive(true);
virtualCam.enabled = true;
freeLookCam.enabled = false;
Cursor.visible = true;
camerasContorl.enabled = false;
/*if(securityKeyPad.GetComponent<SecurityKeypadKeys>().UnlockedCode() == true)
{
securityKeyPad.SetActive(false);
virtualCam.enabled = false;
freeLookCam.enabled = true;
Cursor.visible = false;
anim.Play("Crate_Open");
}*/
//anim.Play("Crate_Open");
playAnimOnce = true;
}
}
}
else if (playAnimOnce)
{
securityKeyPad.SetActive(false);
virtualCam.enabled = false;
freeLookCam.enabled = true;
Cursor.visible = false;
camerasContorl.enabled = true;
anim.Play("Crate_Close");
playAnimOnce = false;
}
}
private void HandleInputCode(int inputCode)
{
if (inputCode == _targetCode)
{
Debug.Log("Code correct!", this);
anim.Play("Crate_Open");
// TODO whatelse has to be done
}
else
{
Debug.Log($"WRONG CODE: Expected {_targetCode} but was {inputCode}!", this);
// TODO some wrong code animation?
}
}
}
This screenshot is showing the Security Keypad System GameObject with the script attached to it :
The game start when the Security Keypad (1) is enabled false not active :
Security Keypad System
If I enable true just to show how it looks like the Security Keypad (1) gameobject then each Key cube is like a button with the OnMouseDown event and each cube have attached the script SecurityKeypadKeys :
Security Keypad (1) enabled true just to show how it looks like in the game
The Security Keypad GameObject is the small keypad system on the left in the scene view and when the player is getting closer to it then the Security Keypad (1) the bigger one is getting active.
On the bottom the gameobject Security Keypad Text is the Text Mesh that should show the numbers pressed.
On the GameObject Crate_0_0 is attached the script UnlockCrate and as target code for testing I added 12345678
The problem now is that it's never getting to the HandleKeyPressed method in the SecurityKeypadSystem script. I used a break point and it's never get there.
I also checked with a break point on the SecurityKeypadKeys script and it's getting the pressed number name but it's never get to the HandleKeyPressed method.
As mentioned there are some uncleared things but most importantly: I would make the entire system more event driven and not poll-check stuff in Update every frame.
I would also separate the responsibilities for each component as clear as possible. E.g. like
SecurityKeypadKeys is only responsible for handling it's own key press. It doesn't know/care what happens with this keypress. It doesn't even know who will handle it or that something like a code or display text exist.
SecurityKeypadSystem this is responsible for handling key presses, store the so far input code, control the display, combine the digits and fire an event once a code is complete. It has no further knowledge about what will happen with this code. It doesn't even know who will handle it
UnlockCrate is in your setup the most "powerful" class. It enables/disables the entire SecurityKeypadSystem, handles the code once it is complete, validates it and finally is responsible for opening the box .. or not. It doesn't have to know that something like a display text exists - it only cares about the final code.
So it could look somewhat like e.g.
public class SecurityKeypadKeys : MonoBehaviour
{
// I would rather go this way round
// Configure the number for each key via the Inspector
// they will then set their own names for debugging
// I wouldn't the other way round rely on that the names are correct
[SerializeField] private int _number;
// Here you can attach callback handlers that will be executed
// For each time this key is pressed
public event Action<int> onKeyPressed;
private void Awake()
{
name = $"Key {_number}";
}
private void OnMouseDown()
{
// This class is only responsible for invoking its event
// It doesn't know and has no authority over how many digits are allowed in the display etc
// it doesn't even know a display exists or that the values get stored by someone
onKeyPressed?.Invoke(_number);
}
}
Then one step up in the System you register a callback handler to these keys so every time a key is pressed you update your text field and store the values:
public class SecurityKeypadSystem : MonoBehaviour
{
[Header("References")]
// rather let this class control the display text
[SerializeField] private TextMesh _text;
[Header("Settings")]
// also rather let this class control the length of a code
[SerializeField] private int _codeLength = 8;
[Header("Debugging")]
[SerializeField] private GameObject[] _keyPadNumbers;
[SerializeField] private List<int> _code = new List<int>();
// This will be invoked once the code length has reached the target length
public event Action<int> OnCodeComplete;
// Start is called before the first frame update
private void Start()
{
_keyPadNumbers = GameObject.FindObjectsOfType<SecurityKeypadKeys>();
// register a callback to each key that handles the numbers
foreach(var keyPadNumber in _keyPadNumbers)
{
// It is save to remove an event even if it hasn't been added yet
// this makes sure it is only added exactly once
// only adding this here for the case you later have to move this again to Update for some reason ;)
keyPadNumber.onKeyPressed -= HandleKeyPressed;
keyPadNumber.onKeyPressed += HandleKeyPressed;
}
}
private void OnDestroy()
{
// just for completeness you should always remove callbacks as soon as they are not needed anymore
// in order to avoid any exceptions
foreach(var keyPadNumber in _keyPadNumbers)
{
keyPadNumber.onKeyPressed -= HandleKeyPressed;
}
}
// this is called when a keypad key was pressed
private void HandleKeyPressed(int value)
{
// add the value to the list
_code.Add(value);
_text.text += value.ToString();
// Check if the code has reached the target length
// if not do nothing
if(_code.Count < _codeLength) return;
// if it reached the length combine all numbers into one int
var exponent = code.Count;
var finalCode = 0;
foreach(var digit in _code)
{
finalCode = digit * Mathf.Pow(10, exponent);
exponent--;
}
// invoke the callback event
OnCodeComplete?.Invoke(finalCode);
// and reset the code
ResetCode();
}
// Maybe you later want an option to clear the code field from the outside as well
public void ResetCode()
{
_code.Clear();
_text.text = "";
}
// also clear the input if this gets disabled
private void OnDisable()
{
ResetCode();
}
}
So finally again from the last class you would add another callback handler which validates the User input and triggers your unlocking
public class UnlockCrate : MonoBehaviour
{
[Header("Settings")]
[SerilaizeField] private int _targetCode;
public GameObject player;
public Animation anim;
public IKControl ikControl;
public InteractableItem interactableItem;
public CinemachineVirtualCamera virtualCam;
public CinemachineFreeLook freeLookCam;
public CamerasControl camerasContorl;
private bool playAnimOnce = false;
[SerializeField] private SecurityKeypadSystem securityKeypadSystem;
private void Start()
{
// as before attach a handler that is triggered once the system completes one code
securityKeypadSystem.OnCodeComplete -= HandleInputCode;
securityKeypadSystem.OnCodeComplete += HandleInputCode;
}
private void OnDestroy()
{
securityKeypadSystem.OnCodeComplete -= HandleInputCode;
}
private void Update()
{
var distance = Vector3.Distance(player.transform.position, transform.position);
if (distance <= interactableItem.distance)
{
if (!playAnimOnce)
{
if(ikControl.handFinishedMove == true)
{
securityKeyPad.SetActive(true);
virtualCam.enabled = true;
freeLookCam.enabled = false;
Cursor.visible = true;
camerasContorl.enabled = false;
/*if(securityKeyPad.GetComponent<SecurityKeypadKeys>().UnlockedCode() == true)
{
securityKeyPad.SetActive(false);
virtualCam.enabled = false;
freeLookCam.enabled = true;
Cursor.visible = false;
anim.Play("Crate_Open");
}*/
//anim.Play("Crate_Open");
playAnimOnce = true;
}
}
}
else if (playAnimOnce)
{
securityKeyPad.SetActive(false);
virtualCam.enabled = false;
freeLookCam.enabled = true;
Cursor.visible = false;
camerasContorl.enabled = true;
anim.Play("Crate_Close");
playAnimOnce = false;
}
}
private void HandleInputCode(int inputCode)
{
if(inputCode == _targetCode)
{
Debug.Log("Code correct!", this);
anim.Play("Crate_Open");
// TODO whatelse has to be done
}
else
{
Debug.Log($"WRONG CODE: Expected {_targetCode} but was {inputCode}!", this);
// TODO some wrong code animation?
}
}
}
Of course I don't know your entire project so this is just a general idea - I hope I made it clear for you to understand the concept :)
Now I am doing a project for my final term in university and my area changed the scene by gazing(google VR SDK).
At first, I just put a code to change the scene. It worked. But I want some enhance, so I used gaze timer which I watched at youtube (link: https://www.youtube.com/watch?v=bmMaVTV8UqY)
Now, the gaze Timer animation is working but the SceneSwitcher function in NexScene1 code isn't working.
I've done 'build' after adding the new scene that I add gaze timer function.
Also, I used tagged which shown in the youtube.
That's all I did.
public class VRGaze : MonoBehaviour {
public Image imgGaze;
public float totalTime = 2;
bool gvrStatus;
float gvrTimer;
public int distanceOfRay = 10;
private RaycastHit _hit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (gvrStatus)
{
gvrTimer += Time.deltaTime;
imgGaze.fillAmount = gvrTimer / totalTime;
}
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0.5f));
if(Physics.Raycast(ray, out _hit, distanceOfRay))
{
if(imgGaze.fillAmount == 1 && _hit.transform.CompareTag("NexScene1"))
{
_hit.transform.gameObject.GetComponent<NexScene1>().SceneSwitcher();
}
}
}
public void GVROn() {
gvrStatus = true;
}
public void GVROff() {
gvrStatus = false;
gvrTimer = 0;
imgGaze.fillAmount = 0;
}
}
public class NexScene1 : MonoBehaviour {
public UnityEngine.UI.Scrollbar obj_scroll_;
public GameObject player;
public void PointEnter()
{
StartCoroutine(TimeToAction());
}
public void PointExit()
{
StopAllCoroutines();
}
public void SceneSwitcher()
{
SceneManager.LoadScene("Page2");
}
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Not an actual error but just the SwitchScene function is not called at VRGaze
Not an error but the console says:
It is recommended to use GvrPointerPhysicsRaycaster or
GvrPointerGrahpicRaycaster with GvrPointerInputModule.