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.
Related
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShootBullets : MonoBehaviour
{
public float bulletDistance;
public bool automaticFire = false;
public float fireRate;
public Rigidbody bullet;
private float gunheat;
private bool shoot = false;
private GameObject bulletsParent;
private GameObject[] startpos;
// Start is called before the first frame update
void Start()
{
bulletsParent = GameObject.Find("Bullets");
startpos = GameObject.FindGameObjectsWithTag("Fire Point");
}
private void Fire()
{
for (int i = 0; i < startpos.Length; i++)
{
Rigidbody bulletClone = (Rigidbody)Instantiate(bullet, startpos[i].transform.position, startpos[i].transform.rotation, bulletsParent.transform);
bulletClone.velocity = transform.forward * bulletDistance;
Destroy(bulletClone.gameObject, 0.5f);
}
}
// Update is called once per frame
void FixedUpdate()
{
if (automaticFire == false)
{
if (Input.GetMouseButtonDown(0))
{
Fire();
}
}
else
{
if (shoot == true)
{
Fire();
shoot = false;
}
}
if (gunheat > 0) gunheat -= Time.deltaTime;
if (gunheat <= 0)
{
shoot = true;
gunheat = fireRate;
}
}
}
now the bullets firing up the air and i want the bullets to fire to a target with physics.
the main goal later is to make some kind of side mission where the player third person view should shoot on object and if and when hitting the object the object will fall down and then the player will be able to pick it up.
What I'm trying to do is have my player stop moving so I can play animation through a trigger-event or just a custscene.
What I expect was for one of them to trigger the timer then play animation>player move.. like a cut-scene
Also there are no errors In any of them They just didn't stop player from moving or just stop the player when starting the game(or when I press play it just set forwardMovement to 0)
Here's the code I use:
public class Player_controls : MonoBehaviour
{
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
public int forwardMovement = 1000;
public void Update()
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
}
Things that I tried:
public void ForwardMovement()
{
forwardMovement = 0;
Invoke("Action", 2f);
}
public void Action ()
{
forwardMovement = 1000 ;
}
Which only works for ForwardMovement(); method nothing else
I tried these two things also:
Public static class MonoExtensions
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public float Delayer = 10f;
public static class MonoExtensions
{
public static void Timed_delay(this MonoBehaviour mono,Action function, float Delayer)
{
mono.StartCoroutine(Timed_delayRoutine(function,Delayer));
}
static IEnumerator Timed_delayRoutine(Action function, float Delayer)
{
yield return new WaitForSeconds(Delayer);
function();
}
public class `Player_Controls`: MonoBehaviour
{
public void PM ()
{
forwardMovement = 0;
}
void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
this.Timed_delay(PM, Delayer);
}
}
}
Which just stop the player from moving an nothing else.
What I also tried was:
public class Player_Controls : MonoBehaviour
{
void Start()
{
StartCoroutine(ForwardMovement());
}
IEnumerator ForwardMovement()
{
forwardMovement = 0;
yield return new waitforseconds(Delayer);
forwardMovement = 1050;
}
void OnTriggerEnter(collider other)
{
if (CompareTag("Power_up"))
{
ForwardMovement();
}
}
}
Which did not work as in(it works but the timer part does nothing, so the player can't move when started the game )
Different way I tried
public class Player_Controls : MonoBehaviour
{
OnTriggerEnter(collider other)
{
Startcroutine(ForwardMovement ));
}
}
it didn't work but no Errors.
I tried this one by jazzhar:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if you're player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
It sorta works in a way if you set if
if (stopMoving == true)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
and
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = true;
}
then the player would be able to move but it will not trigger if hit the cube
it didn't work either but no Errors.
And some other timers I did but forgotten....
_________________________________________________________________March/6/21
public float Delayer = 10.0f;
I think found solution by doing this
private void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
Delayer -= Time.deltaTime; <- this part giving me the error
if (Delayer => 0)
{
forwardMovement = 0;
}
}
}
but their one problem it giving me the this error Cannot convert lambda expression to type 'bool' because it is not a delegate type [Assembly-CSharp]csharp(CS1660) I don't know much about this even searching about doesn't help either
__________________________________________________________________March 28/21
this script is under player controls
this one works I made sure by doing Debug.Log("test");
void OnTriggerExit(Collider collision)
{
if (collision.gameObject.CompareTag("Power_up"))
{
forwardMovement = 0;
}
if (forwardMovement <= 0)
{
Debug.Log("test");
}
This might be a solution to you're problem, Fire-Source!:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if youre player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
This code uses a LayerMask, to create 1 click on any object and in the inspector go:
Click on Layer:
Add Layer:
Write in User Layer 6, StopMovement (or anything else).
Than in the object that should stop player movement:
Click on layer:
Than select the Layer that says StopMovement.
And in you're player's script drag the object into the rb variable.
and in "WichObjectStopsMovement" assign the StopMovement layer.
This should take care of everything is that ok?
I'm developing a TopDown 2D game in Unity.
The idea is, when the player steps on a certain tile, a UI with text pops up (already working) and the player stops moving until the player clicks a button (already programmed and working) and the UI disappears.
I was advised to turn the RigidBody2D to kinematic however it doesn't work and it just does what it used to do.
Am I doing something wrong?
Here is the code for the trigger script on the tiles:
public class TriggerScript : MonoBehaviour
{
public string popUp;
public void Start()
{
}
private void OnTriggerEnter2D(Collider2D collision)
{
Rigidbody2D Player = GameObject.Find("Player").GetComponent<Rigidbody2D>();
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
if (collision.gameObject.tag == "Player")
{
pop.PopUp(popUp);
Player.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Kinematic;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
Rigidbody2D Player = GameObject.Find("Player").GetComponent<Rigidbody2D>();
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
pop.closeBox();
Player.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
}
}
PopUpSystem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PopUpSystem : MonoBehaviour
{
public GameObject popUpBox;
public Animator popupanimation;
public TMP_Text popUpText;
public PLayerController mb;
public void PopUp(string text)
{
popUpBox.SetActive(true);
popUpText.text = text;
popupanimation.SetTrigger("pop");
}
public void closeBox()
{
popupanimation.SetTrigger("close");
mb.camMove = true;
}
}
PLayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PLayerController : MonoBehaviour
{
private Rigidbody2D MyRB;
private Animator myAnim;
[SerializeField]
private float speed;
public bool camMove = true;
// Start is called before the first frame update
void Start()
{
MyRB = GetComponent<Rigidbody2D>();
myAnim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (camMove)
{
MyRB.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed * Time.deltaTime;
myAnim.SetFloat("moveX", MyRB.velocity.x);
myAnim.SetFloat("moveY", MyRB.velocity.y);
if ((Input.GetAxisRaw("Horizontal") == 1) || (Input.GetAxisRaw("Horizontal") == -1) || (Input.GetAxisRaw("Vertical") == 1) || (Input.GetAxisRaw("Vertical") == -1))
{
myAnim.SetFloat("LastMoveX", Input.GetAxisRaw("Horizontal"));
myAnim.SetFloat("LastMoveY", Input.GetAxisRaw("Vertical"));
}
}
if (!camMove)
{
MyRB.velocity = new Vector2(0, 0);
}
}
}
TriggerScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerScript : MonoBehaviour
{
public string popUp;
Animator popAnim;
public PLayerController mb;
private void Start()
{
popAnim = GameObject.FindGameObjectWithTag("PopUpBox").GetComponent<Animator>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
var myp = GameObject.FindGameObjectWithTag("Player").GetComponent<PLayerController>();
if (collision.gameObject.tag == "Player")
{
pop.PopUp(popUp);
mb.camMove = false;
}
if (popAnim.GetCurrentAnimatorStateInfo(1).IsName("close"))
{
mb.camMove = true;
Debug.Log("close");
}
}
private void OnTriggerExit2D(Collider2D collision)
{
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
pop.closeBox();
}
}
Things to keep in mind:
1- Make a new tag and call it PopUpBox. then assign this tag to the Trigger GameObject.
2- To the button of the PopUpBox GameObject (the one which is disabled) assign GameManager GameObject and in its function select PopUpSystem.closeBox
3- In both Trigger GameObject and GameManager assign Player in Mb field.
Hope this help you. You can play with that more to get better results.
When I lock the mouse in my C# script and I try to access the Scroll value (in my case scroll.y) I always get 0.
When I hit esc and unlock the mouse the value shows correctly (-1 or 1) when I use the wheel. It also works, if I build the game.
I've created a InputData to manage my input:
using UnityEngine;
using UnityEngine.InputSystem;
[CreateAssetMenu]
public class InputData : ScriptableObject
{
public InputAction MovementAction;
public InputAction LookAction;
public InputAction ScrollAction;
private void OnEnable()
{
MovementAction.Enable();
LookAction.Enable();
ScrollAction.Enable();
}
private void OnDisable()
{
MovementAction.Disable();
LookAction.Disable();
ScrollAction.Disable();
}
}
In this Script, i get the scroll delta:
using UnityEngine;
public class weaponSwitching : MonoBehaviour
{
private int selectedWeapon = 0;
public InputData actions;
private float prevVal = 0;
void Start()
{
SelectWeapon();
}
void Update()
{
Vector2 scroll = actions.ScrollAction.ReadValue<Vector2>();
Debug.Log(scroll.y);
if (scroll.y > 0f)
{
selectedWeapon++;
SelectWeapon();
}
else if (scroll.y < 0f)
{
}
}
Thank you for any help! :)
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();
}
}