Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice

How to properly create a Cinemachine extension?

Discussion in 'Cinemachine' started by dmarqs, Apr 16, 2022.

  1. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    Hello everyone,

    I need to add some modifications to Cinemachine Collider and I tried duplicating (and of course renaming) inside the package and didn't work, Unity never recognized the file (saying because it's inside an immutable folder). Then I copied it to my Assets/Scripts folder and again the CM couldn't identify it through the extension list nor I could add it like a normal component.

    For the last few tries, I simply created a new cs file that uses CinemachineExtension or tried using the #if CINEMACHINE_PHYSICS but again: nothing seems to work. =/

    So what am I missing here? How to properly create a Cinemachine extension? Unity Docs couldn't help, or at least I couldn't find anything anywhere besides what I already tried.

    My settings:
    - Mac M1
    - Unity 2021.2.17f1
    - Cinemachine 2.8.4
     
  2. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    bump. Someone from the Unity team could help me, maybe?
     
  3. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    6,384
    Copying it to your Assets was the right thing to do.

    Once it's outside of the Cinemachine assembly, however, the #If CINEMACHINE_BLABLA defines will all evaluate to false. You have to remove them, or just define them at the top of the file.

    Can I ask what modifications you want to make to the CM Collider? There might be an easier way.
     
  4. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    Hi @Gregoryl , thanks for your reply.

    After a few more tries and errors I managed to copy and paste, exactly the way you said.

    I'm planning for 2 modifications (one of them I already implemented):

    First: check for a list of tags to be verified to be ignored. As I have a lot of tags to be ignored I did the opposite, created a RaycastAllowedTags (copied and paste the Cinemachine Runtime too) that verifies only the allowed tags that can be raycast. Worked perfectly!

    Second: That's what I'm trying to implement at this moment as we speak. I'm not happy with the "damping when occluded" because if I set any number bigger than 0 it goes inside the building when trying to correct. And if I set to 0 it instantly changes the camera position. =/

    So what I'm trying to do now to implement that second modification is to have some kind of "following" so the camera will try to redo the target position changes instead of trying to adapt and goes inside buildings.

    That it! If you have any suggestions for any of these modifications (that I could even use the default Collider instead of my custom one) I'm glad to hear.


    My code for the RaycastAllowedTags (I just modified the RaycastIgnoreTag):

    Code (CSharp):
    1. /// <summary>
    2.         /// Perform a raycast, but only allows objects that have one of the tags in the list
    3.         /// </summary>
    4.         /// <param name="ray">The ray to cast</param>
    5.         /// <param name="hitInfo">The returned results</param>
    6.         /// <param name="rayLength">Length of the raycast</param>
    7.         /// <param name="layerMask">Layers to include</param>
    8.         /// <param name="allowedTags">Allowed tags</param>
    9.         /// <returns>True if something was hit.  Results in hitInfo</returns>
    10.         public static bool RaycastAllowTags (
    11.             Ray ray, out RaycastHit hitInfo, float rayLength, int layerMask, in List<string> allowedTags)
    12.         {
    13.             if ( allowedTags.Count == 0 )
    14.             {
    15.                 if ( Physics.Raycast (
    16.                     ray, out hitInfo, rayLength, layerMask,
    17.                     QueryTriggerInteraction.Ignore) )
    18.                 {
    19.                     return true;
    20.                 }
    21.             }
    22.             else
    23.             {
    24.                 int closestHit = -1;
    25.                 int numHits = Physics.RaycastNonAlloc (
    26.                     ray, s_HitBuffer, rayLength, layerMask, QueryTriggerInteraction.Ignore);
    27.                 for ( int i = 0; i < numHits; ++i )
    28.                 {
    29.                     bool hasIgnoredTag = false;
    30.  
    31.                     for ( int j = 0; j < allowedTags.Count; j++ )
    32.                     {
    33.                         if ( !s_HitBuffer[ i ].collider.CompareTag (allowedTags[ j ]) )
    34.                             hasIgnoredTag = true;
    35.                     }
    36.  
    37.                     if ( hasIgnoredTag )
    38.                         continue;
    39.  
    40.                     //if (s_HitBuffer[i].collider.CompareTag(ignoreTag))
    41.                     //    continue;
    42.  
    43.                     if ( closestHit < 0 || s_HitBuffer[ i ].distance < s_HitBuffer[ closestHit ].distance )
    44.                         closestHit = i;
    45.                 }
    46.                 if ( closestHit >= 0 )
    47.                 {
    48.                     hitInfo = s_HitBuffer[ closestHit ];
    49.                     if ( numHits == s_HitBuffer.Length )
    50.                         s_HitBuffer = new RaycastHit[ s_HitBuffer.Length * 2 ];   // full! grow for next time
    51.                     return true;
    52.                 }
    53.             }
    54.             hitInfo = new RaycastHit ();
    55.             return false;
    56.         }
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    6,384
    Sounds good. Please keep me posted about your progress on the damping problem. I don't quite understand your proposed solution but am interested.
     
  6. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    Hi again @Gregoryl,

    So during my implementation, I found another issue. Please, have a look at the video below:



    That's the scene view. Whenever the player/character moves around the corridors the camera keeps popping up. The popping happens because I set "damping when occluding" to 0, of course. And the definition of the new position for the camera happens because VC is kind of between that wall that occludes, so whenever the character moves to the right corridor, the VC is still closer and the camera changes position to satisfy the VC position. And whenever the character moves to the left corridor, the camera tries to satisfy the VC there too, which is causing drastic changes.

    What I'm trying to achieve is: if the camera was set to a new position, the VC should follow that new position too, so what I described above (and in the video) will stop happening.

    Is there a way to easily set this rule through VC or a way to set the VC position to follow the new camera pos in my Custom Collider extension?

    Thanks in advance.
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    6,384
    I don't really understand what that means, but I'm guessing that you want to somehow propagate the de-collided camera position back to the vcam, so that this becomes the new desired camera offset. Is that right?

    Instead of modifying CMCollider, you could write a companion script that takes the CMCollider result, interprets it as a target offset, and pushes that back to the vcam.

    What is in your Body section of the vcam? Can you show its inspector?

    The thing is, though, that in a complex environment you can either pop the camera to the new position or lerp it, but if you lerp it there is no logic to prevent it from going through buildings. For that, you need to pathfind. If you have a navmesh, a good option is to make an invisible NavMesh agent that follows your character. Then, put the vcam on that.
     
  8. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    I could write that companion script for sure, but my question is about how can access and change that rotation. In the video there are 2 pieces of information around the character: the white one is the camera and the red is the CinemachineFreeLook orbiting around. What I'm trying to do now is simply reposition that orbit position to be behind the camera pos, after I set the state.PositionCorrection for the camera.

    Or, instead of changing the PositionCorrection for the camera, change the VM orbit for the X-axis only.



    Screen Shot 2022-04-19 at 18.14.27.png
     

    Attached Files:

  9. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    6,384
    To reposition the orbit, you need to change FreeLook.m_XAxis.Value. I'll need to see the Binding Mode of the FreeLook, because the axis value is interpreted differently, depending on the Binding Mode.
     
  10. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    For some reason, my print with the Binding Mode didn't upload properly. Here it is:

    Screen Shot 2022-04-19 at 18.14.18.png
     
  11. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    6,384
    In SimpleFollowWithWorldUp binding mode, you can use FreeLook.ForceCameraPosition() to put the camera wherever you want. The X axis value will always be 0.
     
  12. dmarqs

    dmarqs

    Joined:
    Oct 16, 2013
    Posts:
    33
    Hi @Gregoryl , thanks for the reply!

    I finally solved it yesterday using the height strategy (from a custom collider extension): Instead of applying the displacement to the camera I applied to the RawPosition, so the CM will always 'follow' the player. This avoids the issue of the camera jumping to other positions when the player is in a tight corridor.
     
    Gregoryl likes this.
  13. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    78
    @Gregoryl I need to update the Confiner2D script. I've copied over the asset into my directory, but of course since I'm not in the assembly I don't have access to ConfinerOven as it's internal (side note: why is this file internal? seems like a useful script for consumers).

    Basically for the confiner, I want it to not abruptly stop at the bounds but instead maybe do some kind of lookahead to when a bound might come up and ease to a halt. Same with on the way out of a bounds, ease back into the following motion.

    Any insight would be greatly appreciated!
     
  14. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    6,384
    It's not public because we're trying to keep the API footprint to a minimum or else support becomes too difficult and flexibility becomes compromised. Maybe a case can be made for making this specific thing public, but the general principle still stands.

    You are proposing to implement a feature that has been requested and is on our backlog. Just saying :)

    You have a couple of options for implementing it yourself:
    1. Copy the ConfinerOven also, and make a custom version of it.
    2. Extend Cinemachine using an asmref, which would allow your extension to see inside CM's internals. Warning: if you choose to do this, there is no guarantee that your extension will continue to work in future versions of CM, because the internals are allowed to change without notice (see above).
     
    Last edited: Jun 14, 2022
    atrivedi7 likes this.
  15. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    78
    @Gregoryl Thank you for the response! Is there some roadmap we can follow to know when that might be released?

    In the meantime, I might try to copy over ConfinerOven as well and see where it takes me.
     
  16. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    78
    @Gregoryl There's also the ThirdParty clipper_library.dll that has a bunch of stuff that'd I'd need if copying over ConfinerOven. Any suggestions on how to bring that stuff over? I have a custom asmdef for our code but I cannot seem to reference the dll in it.

    Thanks in advance :)
     
  17. gaborkb

    gaborkb

    Unity Technologies

    Joined:
    Nov 7, 2019
    Posts:
    776
    Gregoryl and atrivedi7 like this.
  18. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    78
    @gaborkb Thank you for the links. I was able to bring the code into my project successfully.
     
    gaborkb likes this.
  19. atrivedi7

    atrivedi7

    Joined:
    Jul 25, 2013
    Posts:
    78
    @Gregoryl @gaborkb any chance you could give insight on when you might be implementing that feature? Thanks :)