Unity reset Oculus position when key is pressed - c#

I am trying to create a script that will reset (to a specific location) the HMD and controller locations whenever a key is pressed for calibration reasons. I am very new to unity so all I have been able to figure out is how to get key input.
public class resetPosition : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
Debug.Log("pressed");
}
}

You shouldn't directly change the position of the VRCamera.
Rather add a parent GameObject to the camera and change the position of that one instead via e.g. (assuming your script is attahced to the camera)
public class ResetPosition : MonoBehaviour
{
public Vector3 resetPosition;
private void Awake()
{
// create a new object and make it parent of this object
var parent = new GameObject("CameraParent").transform;
transform.SetParent(parent);
}
// You should use LateUpdate
// because afaik the oculus position is updated in the normal
// Update so you are sure it is already done for this frame
private void LateUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("pressed");
// reset parent objects position
transform.parent.position = resetPosition - transform.position;
}
}
}

Related

How can I change the Background of the Camera on Collsion with another Object? ~ Unity

I want to make the Background flash red for a short amount of time when Colliding with an Object.
public class Collide : MonoBehaviour
{
public Camera cam;
// Start is called before the first frame update
void Start()
{
cam = GetComponent<Camera>();
}
// Update is called once per frame
void Update()
{
}
void OnCollisionEnter2D()(Collision2D col)
{
}
}
I am fairly new so this is how far I've come but now I have o clue how to chnage the background color of the camera.

Change scene automatically when all objects are clicked Unity

I'm making a new game in Unity and I'm stuck in my script. I'm really noob in C# scripting. I'm already looking for all information but no luck. The game is very simple, it is 2D game where need just click on bubbles and they are rotating when are clicked. I will describe what I exactly need to create. I need a script when all objects are clicked then scene automatically changes to the next level + I need it to have a timeline, for example, for each level have 30 seconds to click all bubbles, when the time is over the game is over and a window pops up with a message "Game Over" and you can press the Reply and Exit buttons. I really hope that someone helps me. Thanks!
P.S. This is my script now for my gameObjects:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class pop : MonoBehaviour
{
public AudioClip sound;
AudioSource audio;
// Start is called before the first frame update
void Start()
{
audio = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
}
bool wasClicked = false;
private void OnMouseDown()
{
if (!wasClicked)
{
wasClicked = true;
transform.Rotate(0, 0, 180);
audio.PlayOneShot(sound);
}
}
}
You should separate these.
I would have a central manager for the scene change like e.g.
public class Manager : MonoBehaviour
{
[SerializeField] private float timer = 30;
private void Awake ()
{
// Register to an event we will add which is fired everytime
// a pop was clicked
pop.onClicked += PopClicked;
}
private void OnDestroy ()
{
// Don't forget to remove the callback as soon as not needed anymore
pop.onClicked -= PopClicked;
}
private void PopClicked ()
{
// Check if there is no Unclicked pop remaining
if(pop.Unclicked.Count == 0)
{
// if so go to the next scene
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
private void Update ()
{
// Every Frame reduce the timer by the time passed since the last frame
timer -= Time.deltaTime;
// Maybe also update a timer display text here
if(timer <= 0)
{
// if it reaches 0 -> GameOver scene
SceneManager.LoadScene("GameOver");
}
}
}
And then modify your Pop class accordingly with some additional things:
public class pop : MonoBehaviour
{
// Stores all Unclicked instances
// As this is static it is "shared" between all instances or better said
// it is part of the type itself
private static HashSet<pop> _unclicked = new HashSet<pop>();
// Public readonly access
public static HashSet<pop> Unclicked => new HashSet<pop>(_unclicked);
// Event that is invoked everytime a pop is clicked
public static event Action onClicked;
public AudioClip sound;
[SerializeField] AudioSource audio;
void Awake()
{
if(!audio) audio = GetComponent<AudioSource>();
// Add yourself to the collection of Unclicked instances
_uncliked.Add(this);
}
private void OnDestroy ()
{
// Don't forget to also remove in case this is destroyed
// e.g. due to the scene change to GameOver
if(_unclicked.Contains(this)) _unclicked.Remove(this);
}
private void OnMouseDown()
{
// Is this still Unclicked?
if (!_unclicked.Contains(this)) return;
transform.Rotate(0, 0, 180);
audio.PlayOneShot(sound);
// Remove yourself from the Unclicked instances
_unclicked.Remove(this);
// Invoke the event
onClicked?.Invoke();
}
}

Grab objects in Unity like half life 2

I am doing a little, but I do not really understand the scripts. I want grab objects ingame like portal or half life 2 and I was trying to code a little script for that action. I made this:
using System.Collections.Generic;
using UnityEngine;
using System;
public class PIckUp : MonoBehaviour {
public Transform theDest;
void OnKeyDown()
{
GetComponent<Rigidbody>().useGravity = false;
this.transform.position = theDest.position;
this.transform.parent = GameObject.Find("Destination").transform;
}
void OnKeyUp()
{
this.transform.parent = null;
GetComponent<Rigidbody>().useGravity = true;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
OnKeyDown();
}
if (Input.GetKeyUp(KeyCode.F))
{
OnKeyUp();
}
}
}
I attach this script to empty object called Destination, when I add a component in grabbable object in "theDest" I target Destination. If i press F all objects are flying i no need aim to them and deform all boxes too i leave here a picture.
I dont find a easy solution, i follow this scripts but are to complex for me and i dont understand how use them or how attach them to a player or object.
https://answers.unity.com/questions/1459773/picking-upholding-objects-portal-style.html
Well the thing is each and every object in the entire scene with this script attached will react to the key press.
I would rather
put all your objects you want to be able to pick on a certain Layer e.g. "Pickable"
make sure they all have colliders
Never parent Rigidbody, rather use Joints e.g. ConfigurableJoint could be useful here, you can completely customize it and use e.g. it's connectedAnchor in order to force the object to move towards you
have a kinematic rigidbody on "theDest" so we can use it as anchor for the joint
have a collider on "theDest" so that we can check distances between colliders
Additional to the layer I would also use a dedicated script like
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(SpringJoint))]
public class Pickable : MonoBehaviour
{
[SerializeField] private Rigidbody rigidbody;
public Rigidbody Rigidbody => rigidbody;
private void Awake()
{
if(!rigidbody && !TryGetComponnet<Rigidbody>(out rigidbody))
{
Debug.LogError("This component requires a Rigidbody!", this);
}
}
public void MarkActive(bool active)
{
// Your customerhod for marking an object the currently active one
// e.g. change its color, add outline etc
}
}
This fulfills three purposes
allows to check if hit object even is pickable
precached components so we don't need GetComponent over and over again
can implement additional behavior such as the mark active visualization
And then have only one single script on your player and use e.g.
public class PIckUpController : MonoBehaviour
{
// Reference this via the Inspector
[SerializeField] private Rigidbody theDest;
// Adjust this in the Inspector, select your Layer(s) that should be Pickable
[SerializeField] private LayerMask pickableLayer;
// Maximum range for picking objects in units
// only Pickable objects within this range can be grabbed
[SerializeField] private float range = 1;
// How fast to attract picked objects
[SerializeField] private float dragSpeed = 1;
private Pickable currentHit;
private Pickable currentPicked;
private ConfigurableJoint currentJoint;
private void Awake ()
{
if(!theDest) theDest = GameObject.Find("Destination"). GetComponent<Rigidbody>();
}
void PickUp()
{
currentJoint = currentHit.AddComponent<ConfigurableJoint>();
// Todo Completely customizable behavior
currentPicked = currentHit;
}
void Release()
{
Destroy(currentJoint);
// TODO optional give it some impulse to throw it away here e.g.
// (Have to tweak the values of course)
currentPicked.Rigidbody.AddExplosionForce(10, theDest.position, 1f, 0.5f, ForceMode.Impulse));
currentPicked = null;
}
private void Update()
{
// Have we already picked up something?
if(!currentPicked)
{
// No -> we chekc if we are pointing on any object
// within the range
var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out var hit, range, pickableLayer)
{
// yes -> get the Pickable component
if(hit.gameObject.TryGetComponent<Pickable>(out var hitPickable))
{
// Is it a different one than the one we already have?
if(hitPickable != currentHit)
{
// yes -> deselect the current one
if(currentHit)
{
currentHit.MarkActive(false);
}
// And store and select the new one
currentHit = hitPickable;
currentHit.MarkActive(true);
}
}
else
{
// If there is no Pickable component we hit something else
// -> deselect and forget the current hit
if(currentHit)
{
currentHit.MarkActive(false);
currentHit = null;
}
}
}
else
{
// We don't hit anything
// -> deselect and forget the current hit
if(currentHit)
{
currentHit.MarkActive(false);
currentHit = null;
}
}
// Do we have a current hit?
if(currentHit)
{
// yes and pressing F -> pick it up
if (Input.GetKeyDown(KeyCode.F))
{
PickUp();
}
}
}
else
{
// We already have picked up something
// of release F -> release object
if (Input.GetKeyUp(KeyCode.F))
{
Release();
}
else
{
// Todo e.g. make the object move towards the "theDest"
}
}
}
}
This one is the main responsible and does
shoot a Raycast to check which object you are pointing at
can additionally (optional) store and mark the currently hit object (as far as I remember HL2 marks them with an outline)
controls the pickup and release of objects

Is this script resource intensive? If so, how do one improve?

This is a simple script that turns a saw blade in my game. The problem is there is approx 18 active blades on the scene, at a time. I am trying to eliminate any probability of lag. This made me wonder if using such a script in "Update", can cause lag?
public class SawBladesRotate : MonoBehaviour
{
public bool GameOver;
public GameObject Player;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
GameOver = Player.GetComponent<PlayerController>().GameOver;
if(GameOver == false)
{
transform.Rotate(new Vector3(0, 0, -45) * Time.deltaTime);
}
}
}
Put this on top of the Start method as class field
private PlayerController playerController;
and this into Start:
playeController = Player.GetComponent<PlayerController>()
Then re-use the reference:
private void Update()
{
if(playerController.GameOver) return;
//...
}
The rest is fine but ofcourse it always depends completely on your usecase.
Even more efficient it would be to directly reference the Component within unity:
[SerializeField] private PlayerController playerController;
Now you can simply drag&drop the Player GameObject into that field in the Inspector and can get rid of the GetComponent call.

other.transform.SetParent messes up with scale of my player

So i was working on to make my moving platform stable for my player.
I used void OnCollisionEnter2D(Collision2D other)' inside platform container script and used 'player.transform.SetParent(plankTranform);'
But setting player transform to be child of platform transform messes up with scale of player.
My best guess is that platform's scale property is being transferred into player's transform.scale. Is there way to just set tranform.position of platform as parent of player's transform.position?
Using player.transform.SetParent(plankTranform); automatically sets tranform 3 properties i.e (position,scale,rotation) to child object. I dnt really want to deal with scale and rotation in this case
public class BrickMoveVErtical : MonoBehaviour {
public Vector3 positionOne;
public Vector3 positiontwo;
public Vector3 nextposition;
public Transform plankTranform;
/*Empty object is already made on unity editor and its parent of
platform(Plank) and other
empty object "pointB". Point "B" is already mapped on editor and platform
is set to go from its original pos to point B */
public Transform positionBTransform;
public float speed;
// Use this for initialization
void Start () {
positionOne = plankTranform.localPosition;
positiontwo = positionBTransform.localPosition;
nextposition = positiontwo;
}
// Update is called once per frame
void Update () {
move();
}
private void move() {
plankTranform.localPosition = Vector3.MoveTowards(plankTranform.localPosition,nextposition,Time.deltaTime*speed);
if(Vector3.Distance(plankTranform.localPosition,nextposition)<0.1)
{ changeMovementPlank(); }
}
void changeMovementPlank() {
nextposition = nextposition != positionOne ? positionOne : positiontwo;
}
void OnCollisionEnter2D(Collision2D other)
{ if(other.gameObject.tag=="Player")
{
other.transform.SetParent(plankTranform);
}
}
void OnCollisionExit2D(Collision2D other)
{
other.transform.SetParent(null);
}
}
Use SetParent(parent, true);
worldPositionStays
If true, the parent-relative position, scale and rotation are modified such that the object keeps the same world space position, rotation and scale as before.

Categories

Resources