So I'm new to C# I somewhat know Python I couldn't understand how functions work I tried doing something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collisiondetectorleft : MonoBehaviour
{
public class Triggerdetecting()
{
public void OnTriggerStay(Collider other)
{
if (other.attachedRigidbody)
other.attachedRigidbody.AddForce((Vector3.up * 10);
}
}
void FixedUpdate()
{
if (Input.GetKeyDown("space"))
{
//I'm so lost
Triggerdetecting objTriggerdetecting = new Triggerdetecting();
}
}
}
I'm trying to create some sort of hitbox by detecting trigger if a button pressed and meets the condition make the object more faster. I tried few ways to call function non of them worked. Thank you for your time. If you unable to understand what I meant you can ask me I'll try to explain in other ways.
Want something like this:
def detection():
if OnTriggerStay == True:
moveobject up
if Input.GetKeyDown("space")) == True:
detection()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collisiondetectorleft : MonoBehaviour
{
//create bool to set it true or false while inside the object
private bool _canHit;
private void Update()
{
if (_canHit)
{
if (Input.GetKeyDown(KeyCode.A))
{
_canHit = false;
//task
}
}
}
//set _canHit true if object enters trigger
private void OnTriggerEnter(Collider other)
{
if (other.attachedRigidbody)
_canHit = true;
}
//set _canHit false if object exits trigger
private void OnTriggerExit(Collider other)
{
if (other.attachedRigidbody)
_canHit = false;
}
}
I was able to detect and log while true but I didn't figured how to react to object that triggers
I would go the same route as you did in your answer attempt.
The last bit missing in order to b able to actually use the according object is simple: Instead of a bool rather directly store the object
public class collisiondetectorleft : MonoBehaviour
{
private Collider _currenTarget;
private void Update()
{
if (_currenTarget && Input.GetKeyDown(KeyCode.A))
{
Debug.Log($"I am interacting with {_currentTarget}");
_currenTarget = null;
}
}
private void OnTriggerEnter(Collider other)
{
if (!other.attachedRigidbody) return;
_currenTarget = other;
}
private void OnTriggerExit(Collider other)
{
if (other != _currenTarget) return;
_currenTarget = null;
}
}
Related
So I have two scripts one to press a button which changes between two objects, and what I want to do is be able to switch out the second avatar with others when I hit e when near another object. the scripts are working, but I have no clue how to get it to switch
here are the trigger script and the switch script
`
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwitchCharacterScript : MonoBehaviour
{
private const string ButtonName = "E";
// references to controlled game objects
public GameObject avatar1, avatar2;
// variable contains which avatar is on and active
int whichAvatarIsOn = 1;
// Use this for initialization
void Start()
{
// anable first avatar and disable another one
avatar1.gameObject.SetActive(true);
avatar2.gameObject.SetActive(false);
}
// public method to switch avatars by pressing the UI button
public void SwitchAvatar()
{
// processing whichAvatarIsOn variable
switch (whichAvatarIsOn)
{
// if the first avatar is on
case 1:
// then the second avatar is on now
whichAvatarIsOn = 2;
// disable the first one and enable the second one
avatar1.gameObject.SetActive(false);
avatar2.gameObject.SetActive(true);
break;
// if the second avatar is on
case 2:
// then the first avatar is on now
whichAvatarIsOn = 1;
// disable the second one and enable the first one
avatar1.gameObject.SetActive(true);
avatar2.gameObject.SetActive(false);
break;
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.LeftAlt))
{
SwitchAvatar();
}
}
}
`
`
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
public class Trigger : MonoBehaviour
{
public SwitchCharacterScript player;
[SerializeField] private bool triggerActive = false;
public GameObject GameObject;
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Player")
{
triggerActive = true;
}
}
void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.tag == "Player")
{
triggerActive = false;
}
}
private void Update()
{
if (triggerActive && Input.GetKeyDown(KeyCode.E))
{
SomeCoolAction();
}
}
public void SomeCoolAction()
{
}
}
`
In the somecoolaction is where I don't know what to do to be able to switch them; if you could not tell, I am new at this both coding and using StackOverflow.
I could not find anything on how to do something similar, or I did not know what to search for and could not find if anyone had a way to do it or a video or something.
Instead of bools I would rather store the actual reference:
public class Trigger : MonoBehaviour
{
private SwitchCharacterScript player;
void OnTriggerEnter2D(Collider2D other)
{
if (other.TryGetComponent<SwitchCharacterScript>(out var switchCharacer))
{
player = switcCharacter;
}
}
void OnTriggerExit2D(Collider2D other)
{
if (player.gameObject == other.gameObject)
{
player = null;
}
}
private void Update()
{
if (player && Input.GetKeyDown(KeyCode.E))
{
player.SwitchAvatar();
}
}
}
In general to be a bit more dynamic I would rather use an array for the characters and do e.g.
public class SwitchCharacterScript : MonoBehaviour
{
// references to controlled game objects
public GameObject[] avatars;
// variable contains which avatar is on and active
private int whichAvatarIsOn = -1;
// Use this for initialization
private void Start()
{
foreach(var avatar in avatars)
{
avatar.SetActive(false);
}
SwitchAvatar();
}
// public method to switch avatars by pressing the UI button
public void SwitchAvatar()
{
if(whichAvatarIsOn > 0 && whichAvatarIsOn < avatars.Length)
{
avatars[whichAvatarIsOn].SetActive(false);
}
whichAvatarIsOn = (whichAvatarIsOn + 1) % avatars.Length;
avatars[whichAvatarIsOn].SetActive(true);
}
}
I am trying to make an object that teleports the player to a different scene when clicked.
I tried following this tutorial: https://youtu.be/PpLJq6AR2J0
This is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Table : MonoBehaviour
{
[SerializeField] private GameObject UiElement;
private void OnTriggerStay2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
UiElement.SetActive(true);
if (Input.GetKeyDown(KeyCode.E))
{
SceneManager.LoadScene("Table1");
}
}
}
void Update()
{
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
UiElement.SetActive(false);
}
}
}
But when I tried it executes everything except
if (Input.GetKeyDown(KeyCode.E))
{
SceneManager.LoadScene("Table1");
}
The code is correct and it executes when it's inside the update function. Is there a fix to this?
The physics framerate update doesn't have to match the game framerate. The Input.GetKeyDown will be true only for one frame so it won't be called. You should put input checks like Input.GetKeyDown inside the update function.
This is not the best way to do it but only to show a way to do it:
private void OnTriggerStay2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
UiElement.SetActive(true);
colliderHit = true;
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if(colliderHit)
SceneManager.LoadScene("Table1");
}
}
Thanks, here is the solution:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Table : MonoBehaviour
{
private bool collided = false;
[SerializeField] private GameObject UiElement;
private void OnTriggerStay2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
collided = true;
}
}
void Update()
{
if (collided == true)
{
UiElement.SetActive(true);
if (Input.GetKeyDown(KeyCode.E) && UiElement == true)
{
SceneManager.LoadScene("Table1");
}
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
collided = false;
UiElement.SetActive(false);
}
}
}
I just used a boolean called collided. That way u can check inside the Update() function.
I made this little script that should turn the light of a point light off and on ... unfortunately only the off button works, after which it doesn't turn on again .... maybe there is some error in the script?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TurnLight : MonoBehaviour {
public GameObject light;
private bool on = true ;
void OnTriggerStay(Collider other) {
if (other.tag == "Player" && Input.GetKey(KeyCode.E) && !on)
{
light.SetActive(true);
on = true;
}
else if (other.tag == "Player" && Input.GetKey(KeyCode.E) && on)
{
light.SetActive(false);
on = false;
}
}
}
Please Check this link to understand OnTriggerStay Function
On Trigger Stay
Also Please check those to differentiate between
Get Key and
Get Key Down
the problem is calling of OnTriggerStay happens continuously and you are using GetKey functions which will return true all times if the player pressed.
So when you use GetKey this will cause Single press on E will be redden multiple times.
Here is my solution
public GameObject light;
bool isPlayerStandingNear = false;
private void Update()
{
if(isPlayerStandingNear)
{
//Debug.Log("isPlayerStandingNear");
if(Input.GetKeyDown(KeyCode.E))
{
Debug.Log("Light State : "+ light.active);
light.SetActive(!light.active);
}
}
}
void OnTriggerStay(Collider other)
{
if (other.tag == "Player")
{
isPlayerStandingNear = true;
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
{
isPlayerStandingNear = false;
}
}
I'm currently working on a game where i have a lightswitch, whenever i'm touching the spherecollider around the switch, the light should turn on. And when i'm not touching the spherecollider anymore, it should turn off. I've not been doing this in a long time, so i've gotten a bit rusty.
public Light ceilingLight;
public bool LS;
private void Update()
{
if (LS == true)
{
ceilingLight.enabled = true;
}
if(LS == false)
{
ceilingLight.enabled = false;
}
}
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
LS = true;
}
if(other.tag != "Player")
{
LS = false;
}
}
First: Instead of using Update you rather want it to be event driven and this avoid unnecessary Update calls when nothing changed anyway.
Then as was mentioned in the comment what you currently do is enable the light if the player touches, disable it if anything else touches it.
You rather want to disable it when the player doesn't touch anymore and ignore everything else.
Simply do
public Light ceilingLight;
// optionally additionally configure whether the light should start enabled or not
public bool InitiallyEnabled;
private void Start()
{
ceilingLight.enabled = InitiallyEnabled;
}
private void OnTriggerEnter(Collider other)
{
if(!other.CompareTag("Player")) return;
ceilingLight.enabled = true;
}
private void OnTriggerExit(Collider other)
{
if(!other.CompareTag("Player")) return;
ceilingLight.enabled = false;
}
As alternative you could also use it as a toggle like
private void OnTriggerEnter(Collider other)
{
if(!other.CompareTag("Player")) return;
ceilingLight.enabled = ! ceilingLight.enabled;
}
so with every touch the player would toggle the light state without having to keep pressing it continuously.
Consider that you may need all types of things to be pressable later on in your app, so you could start with a basic Pressable class to handle the basics. You can then add this behavior to the compositing mix of your respective prefab objects (which may be Holdable, Steerable, Pressable and so on):
using UnityEngine;
public class Pressable : MonoBehaviour
{
[SerializeField] protected bool active = false;
[SerializeField] AudioSource pressSound = null;
protected virtual void Start()
{
}
public virtual void Press()
{
if (pressSound != null) { pressSound.Play(); }
active = !active;
}
}
Note the active bool will appear in the inspector, so you can set it to true at start. (You may also want to pass Press(Person person) in case something should be done with the person pressing.)
Now for your specific light switch, you would inherit this and add the logic for just lights:
using UnityEngine;
public class LightPressable : Pressable
{
Light light = null;
protected override void Start()
{
base.Start();
light = GetComponentInChildren<Light>();
UpdateBasedOnActive();
}
public override void Press()
{
base.Press();
UpdateBasedOnActive();
}
void UpdateBasedOnActive()
{
light.enabled = active;
}
}
Good luck!
I want to have the player start from a start position at first. Then start from a checkpoint after they've completed level one. I've tried different iterations of this script, it is supposed to use a bool check if the player has passed through a trigger, and if they have their position will be equal to the checkpoint at Start. It has to remember the bool when the game is turned off and on again.
Right now the player always starts from the checkpoint.
I tried making my own boolean with playprefs but ended up using BoolPrefs, which still didn't work.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public Rigidbody player;
public Transform startPoint;
public Transform checkPoint;
private void Start()
{
if (PlayerPrefsX.GetBool("level01Complete", false))
{
player.transform.position = startPoint.position;
}
if (PlayerPrefsX.GetBool("level01Complete", true))
{
player.transform.position = checkPoint.position;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "HubTrigger")
{
PlayerPrefsX.SetBool("level01Complete", true);
}
else
{
PlayerPrefsX.SetBool("level01Complete", false);
}
}
}
Here is the BoolPrefs script I'm using currently.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerPrefsX
{
public static void SetBool(string name, bool booleanValue)
{
PlayerPrefs.SetInt(name, booleanValue ? 1 : 0);
}
public static bool GetBool(string name)
{
return PlayerPrefs.GetInt(name) == 1 ? true : false;
}
public static bool GetBool(string name, bool defaultValue)
{
if (PlayerPrefs.HasKey(name))
{
return GetBool(name);
}
return defaultValue;
}
}
I am new to using PlayerPrefs so there may just be something obvious that I'm overlooking.
HubTrigger is the trigger you pass through after completing level one. So it should be that the first time you play you start from one spot, then once you pass through hubtrigger, you've completed level one and from then on you start from the checkpoint when you load the game.
PlayerPrefsX looks fine. It just seems like you're using it incorrectly. You should check if (PlayerPrefsX.GetBool("level01Complete", false)), and if that's true, then set the checkpoint position, and set the start position otherwise:
private void Start()
{
if (PlayerPrefsX.GetBool("level01Complete", false))
{
player.transform.position = checkPoint.position;
}
else
{
player.transform.position = startPoint.position;
}
}
For OnTriggerEnter, you really only should set level01Complete there in the event you beat level 1:
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "HubTrigger")
{
PlayerPrefsX.SetBool("level01Complete", true);
}
}