So I have Ctr C Ctr V an Interaction System from YT channel. I have perfectly copied line by line But the only issue was that he was using the old input system and used KeyPressedDown and keyPressedUp to make 2 boolean's which change according what state is the keypressed, I tried to mimic it with new Input system by making it from a button to a Axis value which follows the logic of if its ClickedAxis>0.4 its true and ClockedAxis==0 false, as a quick press it worked so I was happy BUT here comes the bug My if statement is Being Spammed Constantly like none stop. My statement basically say's that if the Interacting is true Do :
bool interacting;
If(interacting)
{
float HoldingDownTimer =Time.DeltaTime;
if(HoldingDownTimer>=5)
{
//Do your task;
}
}
but When I run the statement For some reason it prints 0.0110823 values which are stuck at that range of number's no lower no higher, My theory is that its been spam called.
Here's the Script If your interested for all the components the YT channel is this guy's VeryHotShark
using UnityEngine;
using NaughtyAttributes;
public class LocomotionScript : MonoBehaviour
{
#region Data
[BoxGroup("Animation Handling Data")]
Animator animator;
int isWalkingHash;
[SerializeField] bool movementPressed;
[BoxGroup("Input Handling Data")]
private CharacterController controller;
public MovementInput input;
Vector2 currentMovement;
[SerializeField] float speed = 1;
private Vector3 velocity;
private float gravity = -9.81f;
public Transform ground;
public float distanceToGround = 0.4f;
public LayerMask groundMask;
private Vector2 smoothinMovement;
private float smoothInputSpeed;
private Vector2 tempCurrentMovement;
private bool isGrounded;
public InteractionInputData interactionInput;
#endregion
private void Awake()
{
animator = GetComponent<Animator>();
input = new MovementInput();
controller = GetComponent<CharacterController>();
input.KeyBoard.ASWD.performed = ctx =>
{
currentMovement = ctx.ReadValue<Vector2>();
movementPressed = currentMovement.x != 0 || currentMovement.y != 0;
};
}
private void Start()
{
interactionInput.Reset();
}
void GetInteractionInputData()
{
interactionInput.InteractedClicked = input.KeyBoard.Interact.ReadValue<float>() > 0.1f;
interactionInput.InteractedReleased = input.KeyBoard.Interact.ReadValue<float>() == 0f;
}
private void Update()
{
LocoMotion();
Grav();
Interact();
GetInteractionInputData();
}
void Grav()
{
isGrounded = Physics.CheckSphere(ground.position, distanceToGround, groundMask);
if (isGrounded && velocity.y<0)
{
velocity.y = -2f;
}
velocity.y = gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
void Interact()
{
}
void LocoMotion()
{
tempCurrentMovement=Vector2.SmoothDamp(tempCurrentMovement, currentMovement, ref smoothinMovement, smoothInputSpeed);
Vector3 movement = (tempCurrentMovement.y * transform.forward) (tempCurrentMovement.x * transform.right);
WalkAnimation();
controller.Move(movement * speed * Time.deltaTime);
}
void WalkAnimation()
{
animator.SetBool("WalkingHush", movementPressed);
}
private void OnEnable()
{
input.KeyBoard.ASWD.Enable();
input.KeyBoard.Interact.Enable();
}
private void OnDisable()
{
input.KeyBoard.ASWD.Enable();
input.KeyBoard.Interact.Enable();
}
}
//
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace th
{
public class InteractionController : MonoBehaviour
{
#region Variables
[Header("Data")]
public InteractionData interactionData;
public InteractionInputData interactionInputData;
[Space]
[Header("RaySetting's")]
public float rayDistance;
public float raySphereRadius;
public LayerMask interactableLayer;
#endregion
#region Private
private Camera m_cam;
private bool m_interacting;
private float m_holderTimer = 0.0f;
#endregion
#region BuildIn
private void Awake()
{
m_cam = FindObjectOfType<Camera>();
}
private void Update()
{
CheckForInteractable();
CheckForInteractableInput();
}
#endregion
#region Crafted Methodds
void CheckForInteractable()
{
Ray _ray = new Ray(m_cam.transform.position, m_cam.transform.forward);
RaycastHit _hitInfo;
bool _hitSomething = Physics.SphereCast(_ray, raySphereRadius, out _hitInfo,
rayDistance,interactableLayer);
if (_hitSomething)
{
InteractableBase _interactable = _hitInfo.transform.GetComponent<InteractableBase>();
if (_interactable != null)
{
if (interactionData.isEmpty())
{
interactionData.Interactable = _interactable;
}
else
{
if (!interactionData.IsSameInteractible(_interactable))
interactionData.Interactable = _interactable;
}
}
}
else
{
interactionData.ResetData();
}
Debug.DrawRay(_ray.origin, _ray.direction * rayDistance, _hitSomething ? Color.green : Color.red);
}
void CheckForInteractableInput()
{
if (interactionData.isEmpty())
{
return;
}
if (interactionInputData.InteractedClicked)
{
m_interacting = true;
m_holderTimer = 0f;
}
if (interactionInputData.InteractedReleased)
{
m_interacting = false;
m_holderTimer = 0f;
}
if (m_interacting)
{
if (!interactionData.Interactable.IsInteractible)
return;
if (interactionData.Interactable.HoldInteract)
{
m_holderTimer = Time.deltaTime;
Debug.Log(m_holderTimer);
if (m_holderTimer >= interactionData.Interactable.holdDuration)
{
interactionData.Interact();
m_interacting = false;
}
}
else
{
interactionData.Interact();
m_interacting = false;
}
}
}
#endregion
}
}
///
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace th
{
[CreateAssetMenu(fileName ="Interaction Data",menuName = "InteractionSystem/InteractionData")]
public class InteractionData : ScriptableObject
{
private InteractableBase m_interactible;
public InteractableBase Interactable
{
get => m_interactible;
set => m_interactible = value;
}
public void Interact()
{
m_interactible.OnInteract();
ResetData();
}
public bool IsSameInteractible(InteractableBase _newInteractible) => m_interactible == _newInteractible;
public bool isEmpty() => m_interactible == null;
public void ResetData()=> m_interactible = null;
}
}
//
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "InteractionInputData", menuName = "InteractionSystem/InputData")]
public class InteractionInputData : ScriptableObject
{
private bool m_interactedClicked;
private bool m_interactRelease;
public bool InteractedClicked
{
get => m_interactedClicked;
set => m_interactedClicked = value;
}
public bool InteractedReleased
{
get => m_interactRelease;
set => m_interactRelease = value;
}
public void Reset()
{
m_interactedClicked = false;
m_interactRelease = false;
}
}
//
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace th
{
public interface IInteractible
{
float HoldDurration { get; }
bool HoldInteract { get; }
bool MultipleUse { get;}
bool IsInteractible { get; }
void OnInteract();
}
}
//
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace th{
public class InteractableBase : MonoBehaviour,IInteractible
{
#region Variables
[Header("Interactible Settings")]
public float holdDuration;
[Space]
public bool holdInteract;
public bool multipleUse;
public bool isInteractible;
#endregion
#region Properties
public float HoldDurration => holdDuration;
public bool HoldInteract => holdInteract;
public bool MultipleUse => multipleUse;
public bool IsInteractible => isInteractible;
#endregion
#region Methods
public void OnInteract()
{
Debug.Log("Interacted: " gameObject.name);
}
#endregion
}
}
CodePudding user response:
Well without parsing through your entire code:
once
HoldingDownTimer >= 5
is true you still keep adding more time in the next frame so the condition is still true in the next frame => you will keep calling it all the following frames as well.
You could introduce a flag somewhat like e.g.
private bool alreadyCalled;
and then
if(interacting)
{
if(!alreadyCalled)
{
HoldingDownTimer = Time.DeltaTime;
if(HoldingDownTimer >= 5)
{
alreadyCalled = true;
//Do your task;
}
}
}
else
{
alreadyCalled = false;
}
CodePudding user response:
As far as I understood your code I think:
I found the issue in it actually you are checking if the 'm_holdTimer' >= 'holdDuration' then perform interaction and you are making it equal to 0 on click start and click end.
So it means if the player has continuously held the button then it will not reset 'm_holdTimer'... so it will continue to call the function recursively because player hasn't actually ended the click so there is not any single function which is reseting 'm_holdTimer' to 0. still if you didn't get my point just copy this function and paste it instead of your own and see if it works, if it do work then you can check the difference between line of code then you'll understand it for sure.
void CheckForInteractableInput()
{
if (interactionData.isEmpty())
{
return;
}
if (interactionInputData.InteractedClicked)
{
m_interacting = true;
m_holderTimer = 0f;
}
if (interactionInputData.InteractedReleased)
{
m_interacting = false;
m_holderTimer = 0f;
}
if (m_interacting)
{
if (!interactionData.Interactable.IsInteractible)
return;
if (interactionData.Interactable.HoldInteract)
{
m_holderTimer = Time.deltaTime;
Debug.Log(m_holderTimer);
if (m_holderTimer >= interactionData.Interactable.holdDuration)
{
m_holderTimer = 0f;
interactionData.Interact();
m_interacting = false;
}
}
else
{
interactionData.Interact();
m_interacting = false;
}
}
}
Hope it helps... Happy coding :)