Allowing player characters to interact with objects is key to most any game. The scope of “interacting” is actually pretty broad as it really goes beyond simple animation management when you break the whole process down.
A lot of these tasks (like highlighting the focus object or determining the object to activate) are things that needs to be done regardless if you use the Motion Controller to animate your character or not.
That said, as the ootii assets expand into a holistic game framework it makes sense to include components that help with object interaction.
A good way to start may simply be to break down the steps of object interaction. We can do this by asking questions about how the game will work:
- How will objects be defined as ‘interactable’?
- How will players know what is interactable?
- How will players focus on an object to interact with?
- How will a player activate an interactable?
- Does the player have to be in a specific spot to activate the object?
- What animation will play to activate the object?
- What happens to the interactable once it’s activated?
- Is there a change in the game once the object is activated?
As an example, lets answer these questions for opening a door:
- Interactable doors will include some component or identifier.
- The doors will glow when they are looked at it.
- The player will focus on a door using the camera.
- The player will press the ‘interact’ action alias while focused on the door.
- Yes. We’ll move and rotate the PC before opening the door.
- The character will play a ‘reach forward’ animation.
- The door will swing open to a specified angle.
- The nav mesh path will now allow for crossing through the door.
So, as we can see there’s a lot more than simply using the Motion Controller to play a ‘reach forward’ animation. That means we need to create a whole approach for dealing with interactables.
Of course you don’t have to follow the approach I’m taking here. However, this should provide an expandable framework for most any kind of object interaction.
The InteractableCore is a new component that will be placed on objects in the scene that can be interacted with. This gives each interactable the ability to:
- Define the interaction motion
- Define the interaction animation form
- Define the collider that defines the object shape
- Define the highlight material for focus highlighting
- Define any actor position or rotation requirements
- Define event handlers
To learn more about the InteractableCore, go here (to be done).
When an interactable is being looked at (has focus), we’ll add a material to its list of materials. This will allow us to create a highlight, border, or anything you want.
I’ve included a simple border based on the material shader found here, but you can replace it as needed.
The Trigger Collider allows us to specify a collider the character must be in before the object can have focus. In addition to the raycast from the BasicInteraction motion, this trigger area helps to limit when we can interact with objects.
In this example, the chest can only be interacted with if you are in the trigger collider which is in front of the chest.
Base Interaction Motion
This motion is similar to the other ‘basic’ motions as it allows us to specify a form that will specify which animation plays for the action. In this way, we can have a ‘bend down’ animation, ‘reach up’ animation, etc.
The motion is also responsible for determining what has ‘focus’. We do this through a continuous raycast.
In some cases, the InteractableCore may specify a position or rotation that the character must be in before the object can be interacted with. So, we’ll specify a walk motion and speeds that allow us to get to that spot.
Each of the interaction animations will use an animation event to specify when the interaction takes place. This allows us to change the timing based on the individual animations.
Basic Walk Run Motion
To help support shifting to a specific position or rotation for interacting with an object, you should include another BasicWalkRun motion in your motion list. This motion would be disabled by default as the BasicInteraction motion will activate and deactivate as needed.
The strafe is nice as it support side stepping.
Ensure the following properties are set:
Name = Controlled Walk (or matches the BasicInteraction's property) Priority = 20 (or higher than other Walk Run motions) Activate With Target = Unchecked Activation Alias = Blank Rotate With Input = Unchecked Rotate With Camera = Unchecked
Once an object is interacted with, we may need to do something specific with the object. As you can imagine, the list of things is limitless. Some common examples would be:
- Door swings open
- Chest swings open
- Lever moves up
- Object is set on fire
- Light turns on
The list goes on and on…
So, it’s up to you to create the unique handlers that you need for your game. As an example, I’ve put together some simple ones.
Here’s what the code looks like to destroy an object:
public class demo_TakeCore : MonoBehaviour
public void OnInteractableActivated(IMessage rMessage)
if (rMessage.Data is GameObject)
This is the function that we’ll assign the InteractableCore’s event handler.
Lets see how this approach comes together using the components above.
- Door object will include an InteractableCore component.
- Door object will include a custom activation handler.
- PC will include a Rigidbody (as IsKinematic).
- PC will include the BasicInteraction motion.
- PC will include a disabled BasicWalkRunStrafe motion.
- BasicInteraction continuous raycast finds InteractableCores to focus on.
- Door’s InteractableCore will get notified and enable the focus material.
- Player activates the BasicInteraction motion with a key press.
- BasicInteraction will move character to the correct position and rotation.
- BasicInteraction will play the animation form specified in the InteractableCore.
- BasicInteraction animation event fires and the InteractableCore is notified.
- InteractableCore calls the custom activation handler.
- The activation handler opens the door.
You can customize this approach in a couple of ways.
- Change the activation handler to do anything you want (requires coding).
- Add a different animation for unique interactions.
- Add a different material/shader for unique focus highlighting.
- Override the BasicInteraction to change how the raycast works.
Raycast vs. ConeCast
One thing I don’t like is that the current raycast in the BasicInteraction motion is very specific. Since it shoots from the camera, you have to look exactly at the Raycast Collider of the InteractableCore in order to focus on the object. I’d rather that raycast be more of a cone.
That’s something you can change by modifying the BasicInteraction motion’s TestActivate() function (line 243) or overriding TestActivate(). You can change the search mechanism to anything you want.
I will probably change it in the future as well after I research some other games.