#Make the camera subscribe to the event

1 messages · Page 1 of 1 (latest)

formal blade
#

Dal can you help lay out some pseudo for this?

#

@winter berry What is the cam subbing to, if the camera should be the one dictating whether it's 2d or 3d movement code to be ran?

winter berry
# formal blade <@335967437315112961> What is the cam subbing to, if the camera should be the on...

Depends on the context but your original concern was to remove the necessity of having to reference of the camera with the movement code. My assumption is that movement code would be some controller and camera would subscribe functionalities to events - move left, right, up, down etc. Camera would handle how it behaves and the movement code would handle when it should be occurring - the normal pattern.

formal blade
#

Yeah maybe I'm just a little confused.

#

I'm using the OnMove() method from Unity's Input System via "Send Messages".

#
    public void OnMove(InputValue movementValue)
    {
        Vector2 _movementVector = movementValue.Get<Vector2>();
        _movementVector.Normalize();
        _movementX = _movementVector.x;
        _movementY = _movementVector.y;

        Vector3 _camForward = _cameraMainTransform.forward;
        Vector3 _camRight = _cameraMainTransform.right;
        _camForward.y = 0f;
        _camRight.y = 0f;
        _camForward.Normalize();
        _camRight.Normalize();


        //if (3dCamEnabled)
        // 3D Movement 
        //_movement = _camRight * _movementX + _camForward * _movementY;

        // 2D Movement - The 'Z' axis is oriented as left and right based on camera orientation.
        _movement = new Vector3(0, 0, -_movementX);
    }
#

So I have trigger zones that switch from a 2d cam to 3d cam, but I'm not quite getting how i can switch the movement code as well.

winter berry
formal blade
#

When it's the "2d" cam enabled, then player should only be allowed to move left/right.

#

Not sure I understand that question completely.

#

I'm just trying to understand an event way of doing:

if (3dCam) my3dmovement line of code.
else my 2dmovement line of code
winter berry
#

How are you changing between 3d and 2d? If you're disabling/enabling something, you could subscribe behaviors and unsubscribe behaviors when enabling/disabling. Camera's would need to know the controller but the controller (event manager) would not need to know the cameras.

formal blade
#

Yes, disabling/enabling CM cameras.

#

One 3d CM cam, and one 2d CM cam.

#

I don't know why, but I still can't wrap my head around events. High level, I get it, but I struggle to implement. 😦

#

I'm not making the connection on how i would be changing the _movement code in that method with the toggling of the cameras via events.

#

Only a condtional statement with direct references make sense :/ * to me

winter berry
#
OnEnable()
    Subscribe my movement function to the controller
OnDisable()
    Unsubscribe my movement function to the controller```
#

Give me a sec. Seeing if I can get some mediocre example up and running.

formal blade
#

Thanks mate.

#

No rush ill be here

formal blade
#

Hopefully it's not soo hard lol 😭

#

@winter berry I may hop off here soon, but feel free to DM or @ me in UUD.

winter berry
formal blade
winter berry
# formal blade Sounds good. No problem, thanks.
public class PlayerController : MonoBehaviour
{
    public event Action<Vector3> OnMove;
    private Vector3 inputDirection;
    private void Update()
    {
        inputDirection.x = Input.GetAxis("Horizontal");
        inputDirection.y = Input.GetAxis("Vertical");
        OnMove(inputDirection.normalized);
    }
}``````cs
public class CamController : MonoBehaviour
{
    [SerializeField] PlayerController pc;
    [SerializeField] Rigidbody rb;
    [SerializeField] float speed = 10f;
    private void OnEnable()
    {
        pc.OnMove += Move;
    }
    private void OnDisable()
    {
        pc.OnMove -= Move;
    }
    private void Move(Vector3 movementDirection)
    {
        var velocity = rb.velocity;
        velocity = transform.forward * movementDirection.y + transform.right * movementDirection.x;
        velocity.y = rb.velocity.y;
        rb.velocity = velocity * speed;
    }
}``````cs
public class CameraFocus : MonoBehaviour
{
    [SerializeField] GameObject first, second;
    private void OnTriggerEnter(Collider other)
    {
        if (other.TryGetComponent(out PlayerController _))
        {
            first.SetActive(true);
            second.SetActive(false);
        }
    }
    private void OnTriggerExit(Collider other)
    {
        if (other.TryGetComponent(out PlayerController _))
        {
            first.SetActive(false);
            second.SetActive(true);
        }
    }
}```I don't know what you're specifically wanting but this is an example of swapping between an orthographic camera and perspective camera. My input is generic and relative to the direction of the virtual camera but you could make it relative to whatever you'd want.
#

In your case, the new Input System would handle input instead of polling - my example is with a event Action. You would define some means to control the object - likely bound to your camera or set to be active relative to your camera. Not wanting to simply flatten or configure the camera at runtime, I just opted to use two cameras - only one active at any one time.

formal blade
#

Thanks @winter berry im going to review a bit later today when I get a break in work. Then I’ll respond.

winter berry
# winter berry ```cs public class PlayerController : MonoBehaviour { public event Action<Ve...

More appropriate names would have been:
InputManager - in charge of acquiring input
PlayerController - in charge of managing player (on the virtual camera)
The last script was simply a means of allowing me to transition between the two very different cams. With one regular camera type and many virtual camera's, you'd not need to disable/manage the regular camera - I used two regular cams with the two virtual cam.

formal blade
#

The in the inspector, I have two Cinemachine cams - One for 2d and one for 3d. By turning one on and the other off, CM automatically switches between them smoothly, no problem.

#

I'm using the CM Trigger Action script (which is basically just the OnTriggerEnter):

#

So you can see, I can drag in an Event - right now it's just increasing distance for the 2d cam, but I would make this "Change to 3d camera", that's easy.

#

But I don't see how when I say "Change to 3d cam ALSO switch the line of movement code from 2d to 3d"

#

I just want "You walked into a trigger that switches to the 3d camera, now the line of code in OnMove() has set the 3d movement code to run: _movement = _camRight * _movementX + _camForward * _movementY;

#

If you step into a trigger that switches to 2d camera, then enable 2d movement code in OnMove():
_movement = new Vector3(0, 0, -_movementX);

#

OnMove() is using Send Messages, via the Player Input component.

winter berry
formal blade
#

Yes, well one is a FreeLook other is Virtual.

#

So just toggling one on/off will smoothly change no problem.

#

It's really just only the movement code, that I am trying to link up.

#

So enable 3d cam, 3d code runs, disable 3d cam, 2d code runs.

winter berry
formal blade
#

It's basically just an OnTrigger really.

#

With option for Exit as well.

winter berry
#

Seems the component doesn't have any fields for modifying the referenced action. If you're unable to change the function for the trigger action, perhaps it's possible to work around this by having two components - one disabled.

#

Usually these Unity components that allow referencing of methods from the inspector would allow us to change their callback referenced function in code as well.

#

Example: Standard Unity Button allows the referencing of script functions from the inspector and from code.

formal blade
#

Well you can call any function from it? It's just a Unity Event.

#

Am I misunderstanding?

#

That's just a function/script I made to increase distance.

winter berry
#

I'm referring to replacing the referenced function through code.

formal blade
#

Ah, guess I've never done it "from code" probably.

#

Yeah

#

gotcha

winter berry
#

I'm guessing that's what you're wanting? To be able to change out the referred movement function?

formal blade
#

Exactly. Roll into Trigger Zone, it enables 3d camera (i got that portion down), but I need to switch to 3d movement code.

winter berry
#

Either your could attach a intermediate function that manages an event/Action itself or have use multiple of these components.

#

I think it may be worthwhile to implement the first.

formal blade
#

I'm specifically doing this to force myself to understand how to set up Actions, so I'm not exactly sure how to do it at the moment.

winter berry
#

Basically a simple script with some UnityAction (possibly a collection of such) to handle the managing of the callback function so that this trigger action component does not need further interaction (changing). You'd then just manipulate your script component etc.

formal blade
#

I wish I could say some of that made sense to me.

#
    public void OnMove(InputValue movementValue)
    {
        Vector2 _movementVector = movementValue.Get<Vector2>();
        _movementVector.Normalize();
        _movementX = _movementVector.x;
        _movementY = _movementVector.y;

        Vector3 _camForward = _cameraMainTransform.forward;
        Vector3 _camRight = _cameraMainTransform.right;
        _camForward.y = 0f;
        _camRight.y = 0f;
        _camForward.Normalize();
        _camRight.Normalize();

        // 3D Movement 
        _movement = _camRight * _movementX + _camForward * _movementY;

        // 2D Movement - The 'Z' axis is oriented as left and right based on camera orientation.
        //_movement = new Vector3(0, 0, -_movementX);
    }
winter berry
#

I'll try to build a test sample more similar to yours.

formal blade
#

Ok even pseudo is fine, but yes the parts are:

  1. OnMove() is using Unity Input System, via Send Messages.
    a. Within it, I need to switch between 3d movement and 2d movement based on which camera is active.
  2. I have a Freelook camera and a Virtual Camera. When turning on or off one of them, CM will seamlessly switch between.
    a. I already this working with the Trigger zones.
winter berry
#

The easy solution might be to simply have to TriggerActions for the two different behaviors (32/2d)

formal blade
#

Sure, I'm fine with that, but how does that also change the movement code?

winter berry
#

Else you would have to either be able to swap out the TriggerAction's referenced method during runtime or have the TriggerAction reference a single method and have that method invoke subscribed actions (it would be managing an event/action of it's own).

formal blade
#

Yeah I think two TriggerActions sounds the best...

formal blade
winter berry
#
public class PlayerController : MonoBehaviour
{
    public UnityEvent<Vector3> OnMove;
    public GameObject activeCam;
    private Vector3 inputDirection;
    private void Update()
    {
        inputDirection.x = Input.GetAxis("Horizontal");
        inputDirection.y = Input.GetAxis("Vertical");
        OnMove.Invoke(inputDirection.normalized);
    }
}``````cs
public class MoveManager : MonoBehaviour
{
    [SerializeField] Rigidbody rb;
    [SerializeField] float speed = 10f;
    public UnityEvent<Vector3> Move;
    public void MoveXAxis(Vector3 input)
    {
        var velocity = rb.velocity;
        velocity.x = input.x * speed;
        rb.velocity = velocity;
    }
    public void MoveForward(Vector3 input)
    {
        var velocity = input.y * speed * rb.transform.forward;
        velocity.y = rb.velocity.y;
        rb.velocity = velocity;

        rb.rotation *= Quaternion.Euler(0f, input.x, 0f);
    }
    public void MoveLocal(Vector3 input)
    {
        Vector3 velocity = input.x * speed * rb.transform.right + input.y * speed * rb.transform.forward;
        velocity.y = rb.velocity.y;
        rb.velocity = velocity;
    }
    public void MoveGlobal(Vector3 input)
    {
        var velocity = Vector3.right * input.x * speed + Vector3.forward * input.y * speed;
        velocity.y = rb.velocity.y;
        rb.velocity = velocity;
    }
    private void OnEnable()
    {
        var pc = rb.GetComponent<PlayerController>();
        pc.OnMove = Move;
        if(pc.activeCam != null)
            pc.activeCam.SetActive(false);
        pc.activeCam = gameObject;
    }
}``````cs
public class TriggerActivate : MonoBehaviour
{
    [SerializeField] GameObject target;
    public void ActivateCam() => target.SetActive(true);
}```
winter berry
#

An if-statement would make subscribing OnMove obsolete and tightly couple the logic there.. ```cs
public void OnMove(InputValue movementValue)
{
Vector2 _movementVector = movementValue.Get<Vector2>();
_movementVector.Normalize();
_movementX = _movementVector.x;
_movementY = _movementVector.y;

    Vector3 _camForward = _cameraMainTransform.forward;
    Vector3 _camRight = _cameraMainTransform.right;
    _camForward.y = 0f;
    _camRight.y = 0f;
    _camForward.Normalize();
    _camRight.Normalize();

    if(...)
        // 3D Movement 
        _movement = _camRight * _movementX + _camForward * _movementY;
    else
        // 2D Movement - The 'Z' axis is oriented as left and right based on camera orientation.
        _movement = new Vector3(0, 0, -_movementX);
}

Invoking a method could decouple some logic there and would look like...cs
public void OnMove(InputValue movementValue)
{
...
_movement = GetMovement.Invoke();//Event, action ect
}```Else use multiple OnMove for vastly different systems and OnMove would be subscribed Both of the above methods don't really make use of OnMove as an event but perhaps you aren't needing events 🤷‍♂️

winter berry
winter berry
formal blade
#

@winter berry Yes, I do not want to couple with an IF statement. That's my whole point of this exercise 😛

#

I'm not sure I entirely understand all the code. Think I'm getting a bit confused due to OnMove() being the Unity Input System function that is using Send Messages. I don't entirely even understand how that works. For example, i don't have any logic in Update, besides limiting my speed.

#

Maybe I just want:

    public void OnMove(InputValue movementValue)
    {
        ...
        _movement = GetMovement.Invoke();//Event, action ect
    }
winter berry
#

Random example from the net:

#

Yours would probably assign your movement action to the listener.

#

Then when the listener detects an action performed, it'd just execute the subscribed function (3d free move, 2d horizontal etc)

formal blade
#

yea i couldnt figure it out 😦

#
    private void SwitchBetweenMovement() => _movement = _3dCam.isActiveAndEnabled ? Movement3d() : Movement2d();

#

Whatever 😦 lol