Aiming down sight state while crouching

I use a custom preset to adjust my FPS character's position offset while crouching. However, I need to have a custom preset activated when crouching and aiming at the same time to have my character's position offset match the x and y positioning of an "aim down sight" function while keeping the y positioning at a "crouch" level. I'm not sure how I would activate this custom preset while using the aim function that is taken by another preset (the "aim down sight while standing up" preset). See video below for my current state system setup.

 
That sounds about as I expected. Quick question, what exactly would adjusting my character's position offset look like in C#?
 
You can access the position offset directly: FirstPersonPerspectiveItem.PositionOffset
 
This is what I have thus far as someone who is fairly new to C#:

using System.Collections;
using System.Collections.Generic;
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.Shared.Utility;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Motion;
using Opsive.UltimateCharacterController.Utility;
using Opsive.UltimateCharacterController.FirstPersonController.Character;
using Opsive.UltimateCharacterController.FirstPersonController.Character.Identifiers;
using UnityEngine;
using FirstPersonPerspectiveItem;

public class M4A1CrouchAndAim : MonoBehaviour
{
public int PositionOffset;

// Update is called once per frame
void Update()
{
if(Input.GetButtonDown("Fire2") && Input.GetButtonDown("Crouch"))
{
FirstPersonPerspectiveItem.PositionOffset = (-0.227, -1.523, -0.075);
}
}
}

Am I heading in the right direction?
 
Yeah that's a good start. But instead of manually checking if the aim and crouch keys are pressed, it would be better to check if both the aim and crouch abilities are currently active. You'd need to first get a reference to each ability, e.g. var aimAbility = characterLocomotion.GetAbility<Aim>(), then check if each ability is active, e.g. if (aimAbility.IsActive && crouchAbility.IsActive) { .... This page explains in more detail.
 
There are a few basic C# writing issues here. I'll point out a few of them, but you should get familiar with what the errors mean and how to fix them before continuing to write custom scripts:

- You're using FirstPersonPerspectiveItem as both a variable name (var FirstPersonPerspectiveItem = ...) and a type (...GetComponent<FirstPersonPerspectiveItem>). Try changing the variable name (e.g. a lowercase 'f').
- PositionOffset is not a component of the character gameobject. Not sure what you're trying to retrieve by m_Character.GetComponent<PositionOffset>.
- PositionOffset is a variable of type Vector3. So when you assign to it, you need to assign a Vector3. E.g. ...PositionOffset = new Vector3(1, 2, 3).
 
Forgive me, for I am rather new at this coding process. Especially when it comes to UCC. Here is my updated script which is down to only two errors. Not sure how to get the aim ability recognized, is it because it's considered an "item ability"?:
Capture.PNG
Capture2.PNG
 
FirstPersonPerspectiveItem exists in the Opsive.UltimateCharacterController.FirstPersonController.Items namespace, whilst Aim is in the Opsive.UltimateCharacterController.Character.Abilities.Items namespace, so you'll need to add these as namespaces to the top of your script. (I'm sure you don't need some of the other namespaces you've included, you could try commenting them out one at a time to see which aren't being used.) For future reference, you can find the namespace a component lives in by opening up the script (e.g. Aim.cs) and checking the "namespace" value at the very top.
 
Thank you, that got it to compile without error. After testing, the position offset did not change when aiming and crouching simultaneously. I chalked this up to having it on private void Start() instead of Update() since we want to be constantly checking if the player is activating both inputs.


Capture.PNG


However, when we test this in-game, an error pops up as soon as we have the playable character crouch. In addition, the position offset didn't change.


Capture1.PNG


This concerns line 31 of my script. I figured the right place to insert the script was the item itself. What am I missing?
 
You're trying to get the FirstPersonPerspectiveItem component directly from the character gameobject (m_Character.GetComponent<FirstPersonPerspectiveItem>()), but the character doesn't have that component. The FirstPersonPerspectiveItem component is attached to the gun item. So you'll need a reference to the item object and call GetComponent<FirstPersonPerspectiveItem>() on it to get that component. A quick and easy way to do that would just be to have a public variable for the gun item gameobject that you can assign in the inspector, which is fine if you don't need to change which item you're referring to during runtime.
 
That fixed it! However, it looks like my aim ability is active by default even when I'm not using it:

Capture3.PNG

This causes our aim and crouch state to be activated while just crouching and not aiming. Unfortunate. The only solution I could think of is referencing the "Zoom" state on the main camera. That seems to be activating and inactivating properly. The only questions would be how do I get a C# reference for:
A. the camera
B. the view types
and C. the states within the view types.
 
Hm, the aim ability always being active does seem to be a bug actually, I can see it in the demo scene too - I'll pass that on.

For the references:
A. You can get the main camera with Camera.main, and then get the Camera controller component from that, e.g. Camera.main.transform.GetComponent<CameraController>().
B. CameraController.ViewTypes returns an array of all the ViewTypes.
C. ViewType.States returns an array of all the state names listed for that ViewType. (Any other state object works the same way.)
 
My mistake - the Aim ability is setup by default to work that way for the first person view. You can disable the "Always Aim" parameter on the Aim ability to prevent that though.
 
Is this parameter "Always Aim"?
Capture1.PNG


With this disabled, my character holds the weapon out of sight when not aiming down the sights, so that won't do.

Capture2.PNG
Capture3.PNG

Here is my latest stab at trying to get the camera "Zoom" state involved, errors and all. Looks like "combatViewType.States" isn't finding the reference I need.
 
Yeah that's the one, I think the name got changed in an update at some point. You'll likely need to adjust the weapon's offset value whilst not aiming to compensate for the fact that in the animator it won't be using the aim item state index at all times.

For your script - StateObject.States simply returns the array of States associated with it, i.e. you don't pass in any particular type. So you would just get the array of States with var states = combatViewType.States, then iterate through this array to find the state you're looking for, e.g. by checking its Name property. (Take a look at State.cs to see its other properties.)
 
Yeah that's the one, I think the name got changed in an update at some point. You'll likely need to adjust the weapon's offset value whilst not aiming to compensate for the fact that in the animator it won't be using the aim item state index at all times.

For your script - StateObject.States simply returns the array of States associated with it, i.e. you don't pass in any particular type. So you would just get the array of States with var states = combatViewType.States, then iterate through this array to find the state you're looking for, e.g. by checking its Name property. (Take a look at State.cs to see its other properties.)
I there a video example of iterating through a given array in the context of Unity programming? I've set this issue aside for a few months because I didn't have a clue about how any of that works.

That said, I took another stab at it and reduced the errors down to 2.
Capture1.PNG

Capture2.PNG
 
Line 43 - you don't need to pass in a type argument to StateObject.States - it's just an array of states associated with that state object.
Line 46 - you'll need to iterate over the array as I said. I recommend looking up some basic C# tutorials on for/foreach loops, but the general idea is something like:

C#:
var states = myViewType.States;
foreach (var state in states) {
    if (state.IsActive) {
        // do something
    }
}
 
Line 43 - you don't need to pass in a type argument to StateObject.States - it's just an array of states associated with that state object.
Line 46 - you'll need to iterate over the array as I said. I recommend looking up some basic C# tutorials on for/foreach loops, but the general idea is something like:

C#:
var states = myViewType.States;
foreach (var state in states) {
    if (state.IsActive) {
        // do something
    }
}
I really appreciate the help, but I can't make it work this way. My understanding is just too limited. Let's go back to using the aimAbility instead. That got me closer to getting what I needed, compared to using the camera states.

You had said "You'll likely need to adjust the weapon's offset value whilst not aiming to compensate for the fact that in the animator it won't be using the aim item state index at all times.", which is indeed insightful, However, while the aim ability is not active, my character holds the weapon in a "idle" stance that cannot be adjusted using the position offset settings under "First Person Perspective item." See screenshot.
 

Attachments

  • Screenshot 2020-11-26 103915.png
    Screenshot 2020-11-26 103915.png
    192.6 KB · Views: 3
Top