[RELEASED] Rival - DOTS Character Controller

Rival is a DOTS character controller built for extensibility & performance, and made with networking in mind. It comes with a samples project that includes a 3D Platformer and a fully-functional Online FPS built with DOTS NetCode!

IMPORTANT: This asset will only work in DOTS projects. It cannot be added to regular Monobehaviour/GameObject Unity projects

[ Store Page ]
[ Documentation Website ]

8 Likes

Been waiting for this!
Quick question, when you say this:

  • The Hybrid Renderer package is required for rendering in DOTS

I assume this isn’t an actual hard requirement of Rival and it would be possible to use something like GPU Instancer for rendering instead - am I correct?

Yes that’s correct, I mostly wrote the above message for people who aren’t really familiar with DOTS, but Rival doesn’t depend on the HybridRenderer in any way.

Your approach should be fine

1 Like

@PhilSA Hi, I tested the Rival samples, after I installed them (following the “Samples - How to Install” tutorial) most of them worked perfectly. :smile:

The only issue I had was in the Basic Sample, the Player character wasn’t being spawned, and Unity complained of a missing entity during game initialization (more specifically, in BasicSceneInitializationSystem.cs, line 84).

Turns out the sceneInitializer.CharacterSpawnPointEntity wasn’t correctly set up in the Main subscene. So, I just opened the Main subscene, selected the SceneInitialization gameobject, and in the BasicSceneInitializationAuthoring component, I assigned the SpawnPoint gameobject to the “Character Spawn Point Entity” field (this reference was missing after I imported the samples, and even after a full Library Reimport, it was still missing).

After I set up that reference in the inspector, then the character spawned correctly. :slight_smile:

2 Likes

Thank you! Another user mentioned that to me earlier as well, and v0.2 is on the way with a fix. Also contains a fix for compilation errors due to an unrecognized character in the code

1 Like

Hi @PhilSA . How’s the performance on mobile platform with DOTS NetCode?

I haven’t gotten around to building for mobile, but I’ll see if I can do a test soon

1 Like

Hi @PhilSA , everything is running smoothly except I’m having a hard time getting prediction working with Rival. I have a feeling that it might be an issue with the NetCode documentation but I’m not sure.

I think what I expect to see is the Rival.KinematicCharacter body showing up in bold
7234442--870848--upload_2021-6-13_18-42-39.png
after including

public class MobCharacterGhostOverrides : IGhostDefaultOverridesModifier
    {
        public void Modify(Dictionary<string, GhostComponentModifier> overrides)
        {
            // TODO: find a way to not have to clear defaults (translation/rotation)
            overrides.Clear();

            var translationComponentModifier = new GhostComponentModifier
            {
                typeFullName = "Unity.Transforms.Translation",
                attribute = new GhostComponentAttribute { PrefabType = GhostPrefabType.All, OwnerPredictedSendType = GhostSendType.All, SendDataForChildEntity = false },
                fields = new[]
                   {
                        new GhostFieldModifier
                        {
                            name = "Value",
                            attribute = new GhostFieldAttribute{Quantization = -1, Smoothing = SmoothingAction.InterpolateAndExtrapolate}
                        },
                    },
                entityIndex = 0,
            };
            overrides.Add(translationComponentModifier.typeFullName, translationComponentModifier);

            var rotationComponentModifier = new GhostComponentModifier
            {
                typeFullName = "Unity.Transforms.Rotation",
                attribute = new GhostComponentAttribute { PrefabType = GhostPrefabType.All, OwnerPredictedSendType = GhostSendType.All, SendDataForChildEntity = false },
                fields = new[]
                   {
                        new GhostFieldModifier
                        {
                            name = "Value",
                            attribute = new GhostFieldAttribute{Quantization = 100, Smoothing = SmoothingAction.InterpolateAndExtrapolate}
                        },
                    },
                entityIndex = 0,
            };
            overrides.Add(rotationComponentModifier.typeFullName, rotationComponentModifier);

            var characterBodyComponentModifier = new GhostComponentModifier
            {
                typeFullName = "Rival.KinematicCharacterBody",
                attribute = new GhostComponentAttribute { PrefabType = GhostPrefabType.All, OwnerPredictedSendType = GhostSendType.All, SendDataForChildEntity = false },
                fields = new[]
                   {
                        new GhostFieldModifier
                        {
                            name = "RelativeVelocity",
                            attribute = new GhostFieldAttribute{Quantization = 100, Smoothing = SmoothingAction.InterpolateAndExtrapolate}
                        },
                        new GhostFieldModifier
                        {
                            name = "IsGrounded",
                            attribute = new GhostFieldAttribute(),
                        },
                        new GhostFieldModifier
                        {
                            name = "ParentEntity",
                            attribute = new GhostFieldAttribute(),
                        },
                    },
                entityIndex = 0,
            };
            overrides.Add(characterBodyComponentModifier.typeFullName, characterBodyComponentModifier);

            var trackedTransformComponentModifier = new GhostComponentModifier
            {
                typeFullName = "Rival.TrackedTransform",
                attribute = new GhostComponentAttribute { PrefabType = GhostPrefabType.All, OwnerPredictedSendType = GhostSendType.All, SendDataForChildEntity = false },
                fields = new[]
                   {
                        new GhostFieldModifier
                        {
                            name = "CurrentFixedRateTransform",
                            attribute = new GhostFieldAttribute{Quantization = -1, Smoothing = SmoothingAction.InterpolateAndExtrapolate}
                        },
                    },
                entityIndex = 0,
            };
            overrides.Add(trackedTransformComponentModifier.typeFullName, trackedTransformComponentModifier);
        }

        public void ModifyAlwaysIncludedAssembly(HashSet<string> alwaysIncludedAssemblies)
        {
            alwaysIncludedAssemblies.Add("Rival.Runtime");
        }

        public void ModifyTypeRegistry(TypeRegistry typeRegistry, string netCodeGenAssemblyPath)
        {
        }
    }

Which I found in the OnlineFPS sample. I’m just not sure what the steps are after or inbetween. I know that these fields need to be synced but without editing files to include [GhostField]s I’m not sure how to. I have also noticed an Assembly Definition Asset. Where must this be placed? Is it necessary?

I understand that these things may not be an issue with Rival or the documentation so I apologise in advance.

P.S. I cant get into the discord server with the link. Do I need an invitation?

Changed a line in a Unity.NetCode.Editor file that was throwing a NullReferenceException from:

                    attr = defaultComponent.fields.FirstOrDefault(f => f.name == componentField.Name).attribute;

to

                    attr = defaultComponent.fields.FirstOrDefault(f => f.name == componentField.Name)?.attribute;

And now after hitting the [Update Component List] button:
7234589--870884--upload_2021-6-13_20-3-14.png

So although now that I have the commands/and kinematic state synced, it still seems that my CharacterProcessor is behaves differently to the one in the OnlineFPS sample.

What I’m looking to achieve is rubberbanding. Currently, pressing the forward key will not move my character forward until it’s heard back from the server. I’m still digging through the OnlineFPS sample to find the difference between it and my project.

thanks

7234589--870884--upload_2021-6-13_20-3-14.png

you can find more info on that here: https://docs.unity3d.com/Packages/com.unity.netcode@0.6/manual/ghost-snapshots.html

Adding this might help fix the syncing issues

Looks like the link I was using had an expiration date, I’ve updated it in first post!

Hi. Any new updates?

So far I’ve tried a quick android build of the stress test scene, but I get a feeling that my settings for DOTS android builds must be wrong in some way. An empty scene with no characters runs at 15 fps on my galaxy s8

I’ll have to investigate further

2 Likes

hello dev
i am considering purchasing your asset for testing purposes and before I do this i read you have specific requirements for version of unity and the use of DOTS and ECS

however, since Unity recently changed dots to only manually inclusion of each and every dots package + dependencies, it is very difficult to know what is the best environment to set up to start with

can you please include exact list of packages and also their version number or links to a list of these package names in manifest inclusion form (example: com.unity.entities), you use when developing and utilizing your asset, and also with sample packages, i understand that atleast these will be mandatory?

com.unity.entities
com.unity.rendering.hybrid
com.unity.dots.editor

unity has made a real mess of this situation, i do not want to sound demanding i just want to make sure i can test my dev environment for this set up prior to making purchases. thank you for your hard work (i am also thinking about your other asset Kinematic Character Controller, when i can afford to, thank you)

@graphicsayy97

The mandatory requirements are Unity 2020.3 and these packages:

This page will tell you how to setup the whole project to make it DOTS-ready:
https://philsa.github.io/rival-doc/Tutorial/tutorial-setup.html

And the requirements for the samples are:
Samples manifest.json

2 Likes

thanks this helped me alot
keep up the good work…
also please consider making more assets like this for DOTS (maybe optimized third-person grappling hook system controller!!! ill pay good money for that!)

Hi there, did you check for mobile build on android or iOS?
Did you find the android fps issue?

I’ll be looking into this over the upcoming weekend

Wow, your asset looks like it might be a lifesaver for me. I need physics and high network performance for a Battle Royale Game but couldn’t get the Ultimate Chatacter Controller to work with the new networking… so I will give it a try. The thing I would miss most is the awesome “Puppetmaster” Asset (Advanced Ragdolling). Do you think this could be integrated to rival or are these operating in seperate worlds?

There would be no way of making both work at the same time, mostly because they both use a different physics engine

Make sure you look a bit into DOTS before buying. If you’ve already started your project in monobehaviour, you’ll need to restart everything from scratch if you want to use DOTS

@Metamulti @optimise

So I reinstalled my Android SDKs and whatnot, and now I’m getting results that make more sense. However, I haven’t been able to make any android build work with IL2CPP, so this is from Mono builds. I also don’t have an iOS device so I can’t test that

StressTest scene with 1000 moving characters on Galaxy s8 (notice the “StressTestCharacterJobs” in green at the bottom: about 7-8ms):

However, the OnlineFPS sample seems to really struggle on my Galaxy s8. The weird thing is that it looks like the slowness is mostly caused by the “WaitForPresentOnGfxThread”, which in turn causes the netcode prediction system to have to do many frames of re-simulation every frame, because the simulation rate is higher than the final framerate:

I wonder if HybridRenderer V2 is safe for use on mobile at the moment (?). I think at this point, someone would have to do a DOTS + Netcode test on android that is completely unrelated to Rival. It would help removing variables from the equation

1 Like