"All in One" script here

@sampattuzzi

No need for two different scripts… I just tick isRunoverPickup or not, can be modified in realtime

Not sure why, but there is no way to make the player stand still when picking this up except to put in a wait… there is a race condition with movement, just not sure how to fix it, if you have a solution, please post and I will update this script accordingly

Original "All in One" Clickable Pickup
using System.Collections;
using GameDevTV.Inventories;
using RPG.Movement;
using UnityEngine;

namespace RPG.Control
{
    [RequireComponent(typeof(Pickup))]
    public class ClickablePickup : MonoBehaviour, IRayCastable
    {
        Pickup pickup;
        [SerializeField] bool isRunoverPickup = true;

        private void Awake()
        {
            pickup = GetComponent<Pickup>();
        }

        private void OnTriggerEnter(Collider other)
        {
            if (other.gameObject.CompareTag("Player"))
            {
                pickup.PickupItem();
            }
        }

        public CursorType GetCursorType()
        {
            if (pickup.CanBePickedUp())
            {
                return CursorType.Pickup;
            }
            else
            {
                return CursorType.FullInventory;
            }
        }

        public bool HandleRaycast(PlayerController callingController)
        {
            print("hovering on clickable pickup " + name);
            if (Input.GetMouseButtonDown(0))
            {
                DedideOnPickupMethod(callingController);
            }
            return true;
        }

        private void DedideOnPickupMethod(PlayerController callingController)
        {
            if (isRunoverPickup)
            {
                print("this is a runover pickup... be right there!");
                callingController.GetComponent<Mover>().StartMovementAction(transform.position);
            }
            else
            {
                print("I have magic reach!");
                StartCoroutine(MagicReach());
            }
        }

        IEnumerator MagicReach()
        {
            yield return new WaitForSeconds(0.1f); // HACK FIXME this wait makes the player stand still not sure how else to do
            pickup.PickupItem();
        }

        public void SetMagicReach(bool condition)
        {
            isRunoverPickup = condition;
        }
    }
}

2 Likes

Hey @HeathClose,

I’m late to the game here, but I’ve been working my way through the course.

I was able to re-write Sam’s pick-up script and integrate IAction with it in order to be able to use the Action Scheduler created in the RPG Core Combat course.

This way I can run over a pickup and not collect it or I can also click the pickup and run to collect it, but I can also click away to cancel the action of picking up the item.

PickupAction Script

using UnityEngine;
using RPG.Inventories;
using RPG.Movement;
using RPG.Core;

namespace RPG.Control

{

[RequireComponent(typeof(Pickup))]

public class PickupAction : MonoBehaviour, IRaycastable, IAction

{

    Pickup pickup;

    bool canPickUp = false;

    private void Awake()

    {

        pickup = GetComponent<Pickup>();

    }

    public CursorType GetCursorType()

    {

        if (pickup.CanBePickedUp())

        {

            return CursorType.Pickup;

        }

        else

        {

            return CursorType.FullPickup;

        }

    }

    public bool HandleRaycast(PlayerController callingController)

    {

        if (Input.GetMouseButtonDown(0))

        {

            callingController.GetComponent<Mover>().MoveTo(gameObject.transform.position, 1f);

            callingController.GetComponent<ActionScheduler>().StartAction(this);

            canPickUp = true;

        }

        return true;

    }

    private void OnTriggerEnter(Collider other)

    {

        if (other.tag == "Player" &&

            pickup.CanBePickedUp() &&

            canPickUp == true)

        {

            pickup.PickupItem();

        }

    }

    public void Cancel()

    {

        canPickUp = false;

    }

}

}

5 Likes

I like this implementation of the player can run and pass over the item but not pick it up unless intentionally clicked by the player to be picked up.
The only issue I have is my player doesn’t move to the pickup item position on the first click.

I did it like this (not the best way, but it works, and the code can definetly improve some)
I believe i set the isItemDroppedByPlayer bool by the RandomDropper, so if player dropped an item,
he would not pick it up again by collision, unless he clicks on it.

using System.Collections;
using System.Collections.Generic;
using GameDevTV.Inventories;
using RPG.Core;
using RPG.Movement;
using UnityEngine;

namespace RPG.Control
{
    [RequireComponent(typeof(Pickup))]
    public class ClickablePickup : MonoBehaviour, IRayCastable, IAction
    {
        [SerializeField] float pickupRange = 1f;

        GameObject player;
        Pickup savedPickup = null;
        Pickup pickup;
        ActionScheduler actionScheduler;

        public bool isItemDroppedByPlayer = false;

        private void Awake()
        {
            pickup = GetComponent<Pickup>();
            player = GameObject.FindWithTag("Player");

            if(player != null)
            {
                actionScheduler = player.GetComponent<ActionScheduler>();
            }
        }

        private void Update()
        {
            if(savedPickup != null && IsInPickupRange())
            {
                savedPickup.PickupItem();
                Cancel();
            }
        }

        public CursorType GetCursorType()
        {
            if (pickup.CanBePickedUp())
            {
                return CursorType.Pickup;
            }
            else
            {
                return CursorType.FullPickup;
            }
        }

        public bool HandleRaycast(PlayerController callingController)
        {
            if (Input.GetMouseButtonDown(1))
            {
                if (player != null)
                {
                    MovePlayerToPickup();
                }

            }
            return true;
        }

        private void MovePlayerToPickup()
        {
            actionScheduler.StartAction(this);
            if (!IsInPickupRange())
            {
                player.GetComponent<Mover>().MoveTo(transform.position, pickupRange);
                savedPickup = pickup;
            }
            else
            {
                player.GetComponent<Mover>().Cancel();
                pickup.PickupItem();
                savedPickup = null;
            }
        }

        public void Cancel()
        {
            if(player != null)
            {
                player.GetComponent<Mover>().Cancel();
            }
            savedPickup = null;
        }

        public bool IsInPickupRange()
        {
            return Vector3.Distance(transform.position, player.transform.position) < pickupRange;
        }

        private void OnTriggerEnter(Collider other)
        {
            if (other.gameObject.tag == "Player")
            {
                if (isItemDroppedByPlayer == false)
                {
                    pickup.PickupItem();
                    savedPickup = null;
                }
            }
        }
    }
}

Privacy & Terms