How to create Pickup that adds to Attribute value?

tippington

New member
I've created custom Attributes on my player; in addition to Health, I've added resources like Wood, Stone, Metal, etc.

My question is: how can I create a pickup that, when picked up by the player, will add a certain amount to the value of a specified Attribute?

I've looked at the Health Pickup item, but that doesn't seem to allow you to select a different Attribute for it to affect.
 
Take a look at this page: https://opsive.com/support/documentation/ultimate-character-controller/attributes/

You can create your own object, similar to the Health Pickup objects in the demo scene, which modify any attribute.

Here is a very basic example of an object that would increase a "Money" attribute on the player by 1 when picked up:


C#:
namespace Opsive.UltimateCharacterController.Objects.CharacterAssist
{
    using Opsive.Shared.Game;
    using Opsive.UltimateCharacterController.Traits;
    using UnityEngine;
        
    public class MoneyPickup : ObjectPickup
    {
        public override void TriggerEnter(GameObject other)
        {
            var money = other.GetCachedParentComponent<AttributeManager>().GetAttribute("Money");
            if (money != null) {
                money.Value += 1;
            }
        }
    }
}
 
Take a look at this page: https://opsive.com/support/documentation/ultimate-character-controller/attributes/

You can create your own object, similar to the Health Pickup objects in the demo scene, which modify any attribute.

Here is a very basic example of an object that would increase a "Money" attribute on the player by 1 when picked up:


C#:
namespace Opsive.UltimateCharacterController.Objects.CharacterAssist
{
    using Opsive.Shared.Game;
    using Opsive.UltimateCharacterController.Traits;
    using UnityEngine;
       
    public class MoneyPickup : ObjectPickup
    {
        public override void TriggerEnter(GameObject other)
        {
            var money = other.GetCachedParentComponent<AttributeManager>().GetAttribute("Money");
            if (money != null) {
                money.Value += 1;
            }
        }
    }
}

Thanks for the help! Passing through the item now adds to the Attribute as expected, but strangely, the item doesn't disappear after it's "picked up". Also, the pickup text isn't displayed and the pickup audio doesn't play. What am I doing wrong?

Here's my resource pickup object class (with a separate helper class just to serialize the info). Also attached some screenshots of my player setup.

C#:
namespace Opsive.UltimateCharacterController.Objects.CharacterAssist
{
    using UnityEngine;
    using Opsive.Shared.Game;
    using Opsive.UltimateCharacterController.Traits;
    using MoreMountains.NiceVibrations;

    [RequireComponent(typeof(ResourcePickupInfo))]
    public class ResourcePickupBehavior : ObjectPickup
    {
        public override void TriggerEnter(GameObject other)
        {
            var attributeManager = other.GetCachedParentComponent<AttributeManager>();
            var info = GetComponent<ResourcePickupInfo>();
            if (attributeManager == null || info == null) { return; }

            MMVibrationManager.Haptic(HapticTypes.LightImpact);

            switch (info.resourceType)
            {
                case ResourceType.WOOD:
                    attributeManager.GetAttribute("Wood").Value += info.resourceAmount;
                    break;

                case ResourceType.STONE:
                    attributeManager.GetAttribute("Stone").Value += info.resourceAmount;
                    break;

                case ResourceType.METAL:
                    attributeManager.GetAttribute("Metal").Value += info.resourceAmount;
                    break;

                case ResourceType.ENERGY:
                    attributeManager.GetAttribute("Energy").Value += info.resourceAmount;
                    break;
            }
        }
    }
}

C#:
using UnityEngine;

public enum ResourceType
{
    WOOD,
    STONE,
    METAL,
    ENERGY
}

public class ResourcePickupInfo : MonoBehaviour
{
    public ResourceType resourceType;
    public int resourceAmount;
}
 

Attachments

  • Screen Shot 2020-05-19 at 10.30.43 AM.png
    Screen Shot 2020-05-19 at 10.30.43 AM.png
    183.6 KB · Views: 6
  • Screen Shot 2020-05-19 at 10.31.09 AM.png
    Screen Shot 2020-05-19 at 10.31.09 AM.png
    264.1 KB · Views: 6
It looks like you're not calling ObjectPickedUp()? Take a look at how HealthPickup.cs uses it. You can also see the method's definition in ObjectPickup.cs (line 178).
 
It looks like you're not calling ObjectPickedUp()? Take a look at how HealthPickup.cs uses it. You can also see the method's definition in ObjectPickup.cs (line 178).

Yep! That was it -- the object disappears when picked up now, as expected. However, I'm still not hearing a sound or seeing any message upon pickup; The ObjectPickedUp method in ObjectPickup.cs seems to contain logic to play the sound if the player object Is connected to a camera, which it is. So I'm not sure why that's not working :/
 
When calling ObjectPickedUp(gameObjectReference), make sure that the argument you pass in is actually a reference to the player gameObject, not its CapsuleCollider. Something like this should work:

C#:
public override void TriggerEnter(GameObject other)
{
    AttributeManager attributeManager = other.GetCachedParentComponent<AttributeManager>();
    var wood = attributeManager.GetAttribute("Wood");
    if (wood != null) {
        wood.Value += 1;
        ObjectPickedUp(attributeManager.gameObject);
    }
}

Note that if you try to pass in "other" or "other.gameObject", it actually passes in the player's CapsuleCollider. I think this is due to the way TriggerEnter is defined within ObjectPickup.cs.
 
That did it, thanks so much! Very peculiar that it defaults to passing the CapsuleCollider instead of the actual GameObject, but either way, I'm all set on this one.
 
It's something to do with the way ObjectPickup defines TriggerEnter to receive a GameObject, but actually just uses Unity's OnTriggerEnter, which receives a Collider.

Anyway, glad you got it sorted.
 
Top