Unity C# Input for continuous events? - c#

Having some major trouble trying to use the updated Unity Input system, specifically with the Hold interaction. I'd like to continuously run code the code only during the performed phase, and have it do so continuously until the key being pressed is let up. Something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private PlayerInput playerInput;
private PlayerInputActions playerInputActions;
void Awake()
{
playerInput = GetComponent<PlayerInput>();
playerInputActions = new PlayerInputActions();
playerInputActions.Player.Forward.performed += Forward;
playerInputActions.Enable();
}
void onEnable() {
playerInputActions.Enable();
}
void onDisable() {
playerInputActions.Disable();
}
public void Forward(InputAction.CallbackContext context) {
while (context.performed) {
Debug.Log("Hello");
if (context.canceled) {
break;}}
}}
How do I reprogram this in order to function as intended?

Something like this should work:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private PlayerInput playerInput;
private PlayerInputActions playerInputActions;
private bool buttonPressed;
void Awake()
{
playerInput = GetComponent<PlayerInput>();
playerInputActions = new PlayerInputActions();
playerInputActions.Player.Forward.performed += holdCallback;
playerInputActions.Player.Forward.canceled += releaseCallback;
playerInputActions.Enable();
buttonPressed = false;
}
void onEnable() {
playerInputActions.Enable();
}
void onDisable() {
playerInputActions.Disable();
}
void Update(){
if(buttonPressed)
Forward();
}
void holdCallback(InputAction.CallbackContext context){
buttonPressed = true;
}
void releaseCallback(InputAction.CallbackContext context){
buttonPressed = false;
}
void Forward() {
Debug.Log("Hello");
}
}

Related

OnTriggerEnter2D doesn't work after switching scenes

I have a game that is similar to "Flappy Bird" and I have main menu where I can start game and change skin of a pigeon. My skin collection is implemented with scroll rect and in the center there is a trigger which starts an animation of scaling a pigeon, it works fine until I click "start" and the scene changes to game and when I return to my main menu and click "skins" this trigger doesn't work anymore.
Script what is attached to all scroll rect elements to detect collisions with trigger:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResizeFieldScript : MonoBehaviour
{
private Animator _anim;
private void Start()
{
_anim = GetComponent<Animator>();
}
public void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log("Trigger is working");
if(collider.tag == "ResizeField")
{
Debug.Log("Condition is working");
_anim.SetBool("isInTrigger", true);
}
}
public void OnTriggerExit2D(Collider2D collider)
{
_anim.SetBool("isInTrigger", false);
}
}
Script what is attached to an empty object to change scenes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
public class UIController : MonoBehaviour
{
[SerializeField] private List<string> sceneNameList;
private string sceneToFind;
private int index = 0;
public void SceneChanger()
{
sceneToFind = EventSystem.current.currentSelectedGameObject.name;
foreach(string str in sceneNameList)
{
if(str == sceneToFind)
{
SceneManager.LoadScene(index);
index = 0;
break;
}
index++;
}
}
public void Exit()
{
Application.Quit();
}
public void BackMenu()
{
SceneManager.LoadScene(4);
}
}
OnTriggerEnter2D doesn't work after switching scenes. We could use OnTriggerEnter2D to jump scenes.
code show as below:
private void Update() {
// If E is pressed
if (Input. GetKeyDown(KeyCode. E)) {
// scene switching
SceneManager.LoadScene(4);
}
}
private void OnTriggerEnter2D(Collider collision) {
if (collision. tag == "ResizeField") {
// The UI prompts the user to press E to jump
EnterDialog.SetActive(true);
Debug.Log("Condition is working");
// _anim.SetBool("isInTrigger", true);
}
}
Hope it helps you.

Assets\EndTriger.cs(6,1): error CS8803: Top-level statements must precede namespace and type declarations

So i made a starter game from brackeys and i get 3 errors please help me
Script:GameManager
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public bool gameHasEnded = false;
public float restartDelay = 1f;
public void CompleteLevel ()
{
Debug.Log("LEVEL COMPLETE");
}
public void EndGame ()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
Invoke("Restart", restartDelay);
}
}
void Restart ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
script:EndTriger
using UnityEngine;
public class EndTriger : MonoBehaviour
public GameManager gameManager;
{
void OnTriggerEnter()
{
gameManager.CompleteLevel();
}
}
EndTriger:
using UnityEngine;
public class EndTriger : MonoBehaviour
{
public GameManager gameManager;
void OnTriggerEnter()
{
gameManager.CompleteLevel();
}
}

Executing a Function Between Script Files

Tell me please. I have 2 scripts that hang on different Unity objects. The first script is for clicking a button. The second one is for executing the function.
How can I execute the AddItem function if the button is pressed?
Script 1 (button click):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UseButton : MonoBehaviour, IPointerUpHandler, IPointerDownHandler
{
public bool isClick = false;
public void OnPointerDown(PointerEventData ped)
{
isClick = true;
}
public void OnPointerUp(PointerEventData ped)
{
isClick = false;
}
}
Script 2 (Adding Items):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InventoryManager : MonoBehaviour
{
public void AddItem(ItemScriptableObject _item, int _amount)
{
foreach(InventorySlot slot in slots)
{
if (slot.item == _item)
{
slot.amount += _amount;
return;
}
}
foreach(InventorySlot slot in slots)
{
//print(_item+" "+_amount);
if (slot.isEmpty == true)
{
slot.item = _item;
slot.amount = _amount;
slot.isEmpty = false;
slot.SetIcon(_item.icon);
return;
}
}
}
If you dont have a variable on the second script, of the first script, you should do that by using:
GameObject go;
go.GetComponent<InventoryManager>();
try changing the first script to something like:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UseButton : MonoBehaviour, IPointerUpHandler, IPointerDownHandler
{
public bool isClick = false;
void Update()
{
if (isClick)
{
Debug.Log("do something")
}
}
public void OnPointerDown(PointerEventData ped)
{
isClick = true;
}
public void OnPointerUp(PointerEventData ped)
{
isClick = false;
}
}
This way you can modify the variable: is Click easily.

Event Action Doesn't work in state Pattern

I'm using state pattern for my unity game. I have three states; HappyState, SurprisedState and SadState. HappyState is default state. I want the character to jump and enter surprised state by clicking left-mouse. Entering surprised state, a few jobs need to be done which I defined as a void to be subscribed to an event, But it doesn't work!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
public class CapsuleScript : MonoBehaviour
{
public event Action SliderAction;
public Slider slider;
public Text stateText;
public GameObject hands;
public Rigidbody rb;
public CapsuleBasicStates currentstate;
public readonly HappyState happyState = new HappyState();
public readonly SadState sadState = new SadState();
public readonly SurprisedState surprisedState = new SurprisedState();
public SpriteRenderer renderer;
public Sprite happysprite, sadsprite, surprisedsprite;
// Start is called before the first frame update
void Start()
{
slider.value = 0;
renderer = GetComponentInChildren<SpriteRenderer>();
rb = GetComponent<Rigidbody>();
TransitionToState(happyState);
}
public void OnCollisionEnter(Collision other) {
currentstate.OnCollisionEnter(this);
}
// Update is called once per frame
void Update()
{
currentstate.Update(this);
}
public void SetSprite(Sprite sprite)
{
renderer.sprite = sprite;
}
public void TransitionToState(CapsuleBasicStates state)
{
currentstate = state;
currentstate.EnterState(this);
}
public IEnumerator SliderHandler()
{
yield return new WaitForSeconds(1f);
slider.value +=1;
StartCoroutine(SliderHandler());
}
public void IEHandler()
{
StartCoroutine(SliderHandler());
}
}
Here is SurprisedState script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SurprisedState : CapsuleBasicStates
{
public override void EnterState(CapsuleScript player)
{
player.SetSprite(player.surprisedsprite);
player.stateText.text = player.surprisedState.ToString();
player.slider.gameObject.SetActive(true);
player.SliderAction += player.IEHandler;
}
public override void OnCollisionEnter(CapsuleScript player)
{
//player.TransitionToState(player.happyState);
}
public override void Update(CapsuleScript player)
{
if(player.slider.value ==20)
{
player.SliderAction -= player.IEHandler;
player.TransitionToState(player.happyState);
}
}
}
HappyState script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HappyState : CapsuleBasicStates
{
public override void EnterState(CapsuleScript player)
{
player.SetSprite(player.happysprite);
player.stateText.text = player.happyState.ToString();
player.hands.SetActive(false);
}
public override void OnCollisionEnter(CapsuleScript player)
{
}
public override void Update(CapsuleScript player)
{
if(Input.GetButton("Fire1"))
{
player.rb.AddForce(Vector3.up * 150f);
player.TransitionToState(player.surprisedState);
}
if(Input.GetButton("Fire2"))
{
player.rb.AddForce(Vector3.up *250f);
player.TransitionToState(player.sadState);
}
}
}
Few points before I post my solution:
Try to post all scripts related to the question you are asking.
Comment your code or try to explain what each part of your script is doing.
BaseSate.cs
[System.Serializable]
public abstract class BaseState
{
public enum PlayerStates { HappyState = 0, SurprisedState = 1 }
public abstract PlayerStates PlayerState { get; }
public abstract void EnterState(PlayerScript playerScript);
public abstract void UpdateState();
public abstract void ExitState();
}
HappySate.cs
using UnityEngine;
[System.Serializable]
public class HappyState : BaseState
{
public override PlayerStates PlayerState => PlayerStates.HappyState;
private PlayerScript _playerScript;
public override void EnterState(PlayerScript playerScript)
{
_playerScript = playerScript;
Debug.Log($"Entered {PlayerState}");
}
public override void UpdateState()
{
if (Input.GetButtonDown("Fire1"))
{
_playerScript.ChangeState(new SurprisedState());
}
}
public override void ExitState()
{
Debug.Log($"Exited {PlayerState}");
}
}
SurprisedState.cs
using UnityEngine;
[System.Serializable]
public class SurprisedState : BaseState
{
public override PlayerStates PlayerState => PlayerStates.SurprisedState;
private PlayerScript _playerScript;
public override void EnterState(PlayerScript playerScript)
{
_playerScript = playerScript;
// subscribe to sliderAction on enter
playerScript.playerSliderAction += OnSliderChange;
Debug.Log($"Entered {PlayerState}");
}
private void OnSliderChange(float sliderValue)
{
// use Mathf.Approximately instead of == when comparing
// floating numbers.
if (Mathf.Approximately(sliderValue, 20f))
{
_playerScript.ChangeState(new HappyState());
}
}
public override void UpdateState() { }
public override void ExitState()
{
// unSubscribe to sliderAction on exit
_playerScript.playerSliderAction -= OnSliderChange;
Debug.Log($"Exited {PlayerState}");
}
}
PlayerScript.cs
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class PlayerScript : MonoBehaviour
{
[SerializeField]
private SpriteRenderer playerRenderer;
[SerializeField]
private Sprite[] playerStateSprites;
[SerializeField]
private Slider playerSlider;
public UnityAction<float> playerSliderAction;
private BaseState _currentState;
private void Awake()
{
Initialize();
}
private void Update()
{
_currentState.UpdateState();
}
private void Initialize()
{
ChangeState(new HappyState());
// use slider onValueChanged instead of checking slider
// value every frame.
// invoke unity action when the value has been changed.
playerSlider.onValueChanged.AddListener(sliderValue =>
{
playerSliderAction?.Invoke(sliderValue);
});
}
public void ChangeState(BaseState newState)
{
// change state only when it is different
// from previous state.
if (_currentState == newState)
{
return;
}
_currentState?.ExitState();
_currentState = newState;
_currentState.EnterState(this);
playerRenderer.sprite = playerStateSprites[(int)newState.PlayerState];
Debug.Log($"Current State : {_currentState.PlayerState}");
}
}
PlayerScript inspector view
Execution Overview gif:
https://gfycat.com/grimflowerycollardlizard

How to select and deselect in a crossword game

So, im doing a crossword game in Unity Engine, and when i select (with my left click button) a word, the white tiles should turn green (which occurs), but when i stop holding my left mouse click button, it does not turns white again as you can see on the print
And the code is here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using System;
public class Selecionar : MonoBehaviour, ISelectHandler, IPointerClickHandler, IDeselectHandler {
private int acertos;
public static HashSet<Selecionar> todosMeusSelecionaveis = new HashSet<Selecionar>();
public static HashSet<Selecionar> selecionado = new HashSet<Selecionar>();
Renderer myRenderer;
[SerializeField]
Material materialNaoSelecionado;
[SerializeField]
Material materialSelecionado;
void Awake()
{
todosMeusSelecionaveis.Add(this);
myRenderer = GetComponent<Renderer>();
}
public void OnDeselect(BaseEventData eventData)
{
myRenderer.material = materialNaoSelecionado;
}
public void OnPointerClick(PointerEventData eventData)
{
if(Input.GetKeyDown(KeyCode.Mouse0)){
DeselectAll(eventData);
}
OnSelect(eventData);
}
public void OnSelect(BaseEventData eventData)
{
selecionado.Add(this);
myRenderer.material = materialSelecionado;
}
public static void DeselectAll (BaseEventData eventData){
foreach (Selecionar selecionavel in selecionado)
{
selecionavel.OnDeselect(eventData);
}
selecionado.Clear();
}
}
I think you should return inside the if statement on OnPointerClick. When it enters, it executes DeselectAll followed by OnSelect.
Either do:
public void OnPointerClick(PointerEventData eventData)
{
if(Input.GetKeyDown(KeyCode.Mouse0)){
DeselectAll(eventData);
return; // <----
}
OnSelect(eventData);
}
or:
public void OnPointerClick(PointerEventData eventData)
{
if(Input.GetKeyDown(KeyCode.Mouse0)){
DeselectAll(eventData);
} else {
OnSelect(eventData);
}
}

Categories