My object interaction system doesn’t work properly, here are my problems:
-
It doesn’t work on all objects, even though they all have the same components.
-
In this scene it only works with objects at the level where the camera is standing. But when I pick up that object and put it on the ground, the interaction doesn’t work with it anymore.
-
In another scene with the same scripts and objects with the same properties (the CarriableBox game object in here) the system works fine.
-
Components of Objects:
-
PlayerFollowCamera position:
-
Object Transforms:
-
Scripts:
- Script for objects: ObjectGrabbable.cs (1.3 KB)
- Script for player: PlayerPickUpDrop.cs (1.5 KB)
- Interface for ObjectGrabbable.cs IGrabbable.cs (252 Bytes)
You have a lot of errors in the console “Box collider does not support negative scale or size”. I would start there. If you click on the errors while in play mode, it will highlight in the inspector the items with the issues. This will either be caused by negative scale on the transform or negative size on the box collider component.
I would also add Debug logs at multiple points in your code to confirm what exactly is happening or not happening when you press E. For example:
private void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
Debug.Log("E Pressed");
if (objectGrabbable == null)
{
Debug.Log("Try Pickup Grabbable");
// Not carrying an object, try to grab
float pickUpDistance = 4f;
if (Physics.Raycast(
playerCameraTransform.position,
playerCameraTransform.forward,
out RaycastHit raycastHit,
pickUpDistance,
pickUpLayerMask
))
{
Debug.Log("Raycast Hit " + raycastHit.transform.gameObject);
if (raycastHit.transform.TryGetComponent(out objectGrabbable))
{
Debug.Log("Pickup Grabbable");
objectGrabbable.Grab(objectGrabPointTransform);
}
}
}
else
{
Debug.Log("Drop Grabbable " + objectGrabbable);
// Currently carrying something, drop
objectGrabbable.Drop();
objectGrabbable = null;
}
}
}
I’m sorry I forgot to add that: These “Box collider does not support negative scale or size” warnings are not about my current objects but about asset pack’s environment.
Also I have question here: I am using the E key in 2 different scripts for two separate Interacts, both are attached to Player.
Will this cause a problem here?
Other script:
using System.Collections;
using System.Collections.Generic;
using StarterAssets;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerInteract : MonoBehaviour
{
[SerializeField]
private LayerMask boxesLayerMask;
private StarterAssetsInputs starterAssetsInputs;
private Vector3 lastInteractDir;
private void Awake()
{
starterAssetsInputs = GetComponent<StarterAssetsInputs>();
}
private void Update()
{
TryInteract();
}
private void TryInteract()
{
if (Input.GetKeyDown(KeyCode.E))
{
HandleInteractionObjects(); // Interact with objects like interactable boxes
}
else if (Input.GetKeyDown(KeyCode.F))
{
HandleInteractionNPCs();
}
}
private void HandleDirection()
{
Vector2 inputVector = starterAssetsInputs.move;
inputVector = inputVector.normalized;
Vector3 moveDir = new Vector3(inputVector.x, 0f, inputVector.y);
if (moveDir != Vector3.zero)
{
lastInteractDir = moveDir;
}
}
private void HandleInteractionObjects()
{
HandleDirection();
float interactDistance = 2f;
//Vector3 raycastOriginHeight = new Vector3(0, 0.2f, 0);
if (
Physics.Raycast(
transform.position,
lastInteractDir,
out RaycastHit raycastHit,
interactDistance,
boxesLayerMask
)
)
{
Debug.Log(raycastHit.transform);
if (raycastHit.transform.TryGetComponent(out PortableBox box))
{
// Has Box
Debug.Log("it is a box");
box.Interact();
}
}
}
private void HandleInteractionNPCs()
{
float interactDistance = 2f;
var colliderArray = Physics.OverlapSphere(transform.position, interactDistance);
foreach (Collider collider in colliderArray) {
if( collider.TryGetComponent(out NPCInteractable npcInteractable)) {
npcInteractable.Interact();
}
}
}
}
Now I’m sure that the problem is about the level (height) of objects here, but the obect level isn’t a problem in my other scene, I don’t understand.
I have used Debug.Log and I think the problem is in here:
if (
Physics.Raycast(
playerCameraTransform.position,
playerCameraTransform.forward,
out RaycastHit raycastHit,
pickUpDistance,
pickUpLayerMask
)
)
First, when I press E near to my CarriableBox it just worked by here:
if (Input.GetKeyDown(KeyCode.E))
{
Debug.Log("E Pressed");
if (objectGrabbable == null)
{
Debug.Log("Try Pickup Grabbable");
But when I try to get chinese_chandelier_1k object (has higher than others), it worked fine. What is the point here? Can anyone help?
There is nothing wrong with your scripts and it is also perfectly fine to check for the keyinput in multiple scripts like you are doing.
Most likely the issue is that the raycast is too high or not pointing at the object you want to pick up.
I modified your script to draw a debug ray which will be visible in scene view, and added additional log statements to help you understand what is going on. Once you can visualize the raycast you will be able to pinpoint the problem. You can toggle the console logs and the debug ray with the debug flag in the inspector:
using Sirenix.OdinInspector;
using UnityEngine;
using MyScripts;
public class PlayerPickUpDrop : MonoBehaviour
{
[Title("Where to place the grabbable object:")]
[SerializeField] private Transform objectGrabPointTransform;
[SerializeField] private Transform playerCameraTransform;
[SerializeField] private LayerMask pickUpLayerMask;
[SerializeField] private float pickUpDistance = 4f;
[SerializeField] private bool debug = true;
private IGrabbable objectGrabbable;
private bool wasReadyToPickup;
private GameObject lastObjectHit;
private void Update()
{
if (debug)
{
Debug.DrawRay(
playerCameraTransform.position,
playerCameraTransform.forward * pickUpDistance,
Color.red);
bool isReadyToPickup = GetGrabbable() != null;
// only log a status message if status has changed
if (wasReadyToPickup != isReadyToPickup)
{
wasReadyToPickup = isReadyToPickup;
if (isReadyToPickup)
{
Debug.Log("Grabbable Is Ready To Be Picked Up");
}
else
{
Debug.Log("No Grabbable In Range");
}
}
}
if (Input.GetKeyDown(KeyCode.E))
{
if (debug)
{
Debug.Log("E Pressed");
}
if (objectGrabbable == null)
{
objectGrabbable = GetGrabbable();
if (objectGrabbable != null)
{
if (debug)
{
Debug.Log("Pickup Grabbable " + objectGrabbable);
}
objectGrabbable.Grab(objectGrabPointTransform);
}
}
else
{
if (debug)
{
Debug.Log("Drop Grabbable " + objectGrabbable);
}
objectGrabbable.Drop();
objectGrabbable = null;
}
}
}
private IGrabbable GetGrabbable()
{
if (Physics.Raycast(
playerCameraTransform.position,
playerCameraTransform.forward,
out RaycastHit raycastHit,
pickUpDistance,
pickUpLayerMask
))
{
if (lastObjectHit != raycastHit.transform.gameObject)
{
lastObjectHit = raycastHit.transform.gameObject;
if (debug)
{
Debug.Log("Hit By RayCast - " + lastObjectHit);
}
}
raycastHit.transform.TryGetComponent(out IGrabbable grabbable);
if (grabbable != null)
{
return grabbable;
}
}
lastObjectHit = null;
return null;
}
}
1 Like
Thanks a million. Your help is so valuable. I have found the problem.
Even if I use the same prefab in both scenes, still in one scene the rays only go forward, while in the other scene they go in the same direction as the camera, but I still can’t figure out the cause of the problem. What can be the problem? Any ideas?
Also strangely the x and z position values of PlayerFollowCamera in scene 2
(x = 2.048909e and z = -8.707866e-08) despite the same prefab.
0 is not done (I cannot change the position values in the picture).
They also both use the same MainCamera prefab and their values seem to be unchanged.
Okay the solution is so simple: I just assigned the MainCamera transform to playerCameraTransform variable and everything works perfect. Thank you for all answer, I have just return to this project and Unity after 4 months, I forgot even basics and Debugging and I feel like a stupid (don’t take long breaks when u are working on a project xD), thank you for your help and debug tips nextlevel <3
1 Like