Conversation
- Added Rainbow Effect on marker - Single instance of the marker - Enabled jump and glide while auto walking - Removed Animator Contoller from the Global Plugin System
|
Windows and Mac build successful in Unity Cloud! You can find a link to the downloadable artifact below. |
feat: avatar movement using double clickPR number: 7978 Intel Core i3Change samples: 2671
|
daniele-dcl
left a comment
There was a problem hiding this comment.
Besides the 1 change to the grass material that seems unintentional, everything else is minor 👍
| private static readonly int IDLE_STATE = Animator.StringToHash("Idle"); | ||
| private static readonly int EMISSION_COLOR = Shader.PropertyToID("_EmissionColor"); | ||
|
|
||
| [SerializeField] public float rainbowSpeed = 1f; |
There was a problem hiding this comment.
Usually we go with a property with private setter and use [field: SerializeField] on it
| { | ||
| if (transitionedToIdle || animator == null) return; | ||
|
|
||
| AnimatorStateInfo info = animator.GetCurrentAnimatorStateInfo(0); |
There was a problem hiding this comment.
I am not 100% sure if I understood this correctly. It seems the goal is to transition the animator to a given state after a while?
I believe we would want to do that with the exit time of the default state of the animator instead?
Is there a good reason to do it programmatically?
There was a problem hiding this comment.
I was having problems with the animator controller transition and end up doing it programatically. It was a problem with the animation, so reverted this and made the transition directly using the exit time.
| private readonly GameObject markerPrefab; | ||
|
|
||
| // Stores the time of the previous left-click to detect double-clicks. | ||
| private float lastClickTime = float.MinValue; |
There was a problem hiding this comment.
It would be nice to check if it's possible to do this in the input actions asset by using a multi-tap interaction.
There was a problem hiding this comment.
Yeah! I chanted it use the multitap option of the input system.
Explorer/Assets/DCL/Character/CharacterMotion/Systems/UpdatePointAndClickInputSystem.cs
Show resolved
Hide resolved
Explorer/Assets/DCL/Character/CharacterMotion/Systems/UpdatePointAndClickInputSystem.cs
Show resolved
Hide resolved
| }; | ||
|
|
||
| if (World.Has<PointAndClickMovementComponent>(entity)) | ||
| World.Set(entity, component); |
There was a problem hiding this comment.
You were right, we have that. Changed.
| Vector2 screenPos = mouse.position.ReadValue(); | ||
| Ray ray = cameraComponent.Camera.ScreenPointToRay(new Vector3(screenPos.x, screenPos.y, 0f)); | ||
|
|
||
| if (Physics.Raycast(ray, out RaycastHit hit)) |
There was a problem hiding this comment.
Maybe we can consider filtering this out by layer? Maybe also max distance to avoid super far away clicks?
There was a problem hiding this comment.
I've added the max distance configurable in the CharacterControllerSettings. Regarding the layers I would like th player to be able to click anywhere in the scene, the floor and even the avatars, I dont know the right combination of layers here... :S
| m_ValidKeywords: | ||
| - _ADVANCED_LIGHTING | ||
| - _FADING | ||
| - _GPU_GRASS_BATCHING |
There was a problem hiding this comment.
Are changes to this material intentional?
There was a problem hiding this comment.
Yeah i tried my best to not tick these mat changes in the commits but I failed. Shall we include those in the gitignore?
|
@claude review |
|
Claude finished @daniele-dcl's task in 2m 57s —— View job Code Review
SummaryThe feature works conceptually but has several issues that must be fixed before merging. Blocking Issues
REVIEW_RESULT: FAIL ❌ |
| Color emission = Color.HSVToRGB(hue, 1f, 1f) * emissionIntensity; | ||
|
|
||
| foreach (Renderer r in renderers) | ||
| r.material.SetColor(EMISSION_COLOR, emission); |
There was a problem hiding this comment.
GC/Batching Issue: r.material instantiates a per-renderer material the first time it's accessed, which prevents GPU instancing/batching for all renderers sharing that material. More critically, calling this inside foreach every frame is the wrong pattern entirely.
Use a MaterialPropertyBlock instead — it lets you set per-object shader properties without breaking batching or creating material instances:
| r.material.SetColor(EMISSION_COLOR, emission); | |
| if (_propertyBlock == null) _propertyBlock = new MaterialPropertyBlock(); | |
| _propertyBlock.SetColor(EMISSION_COLOR, emission); | |
| foreach (Renderer r in renderers) | |
| r.SetPropertyBlock(_propertyBlock); |
Declare private MaterialPropertyBlock _propertyBlock; as a field.
| private readonly GameObject markerPrefab; | ||
|
|
||
| // Stores the time of the previous left-click to detect double-clicks. | ||
| private float lastClickTime = float.MinValue; |
There was a problem hiding this comment.
CLAUDE.md Violation — System State: lastClickTime is behavioral state stored in the system. The project standard explicitly states: "Systems must not contain state — all state goes into ECS."
The same applies to markerShouldBeHidden on line 48. Both should be moved into ECS components (e.g., a PointAndClickInputStateComponent singleton on the player or a dedicated singleton entity). Holding them here also makes the system untestable since UnitySystemTestBase<T> won't be able to inspect or seed this state.
| if (hasManualMovement) | ||
| { | ||
| markerShouldBeHidden = true; | ||
| World.Remove<PointAndClickMovementComponent>(entity); |
There was a problem hiding this comment.
ECS Safety Violation: World.Remove is a structural change that triggers an archetype move, relocating entity data in memory. The function has ref PointAndClickMovementComponent pcm in its signature, so pcm is an active ref at this call site. Per CLAUDE.md:
"NEVER perform structural changes (Add/Remove that trigger archetype moves) after obtaining a
ref,in, oroutreference to a component."
This applies even though you return immediately after — the structural change can invalidate the Arch ECS chunk iterator for the current query, potentially causing skipped or double-visited entities in the same frame.
The same issue exists at lines 224 and 244.
Fix: collect entities that need removal in a temporary list and remove them after the query completes.
| [field: SerializeField] internal PointAtMarkerVisibilitySettings PointAtMarkerVisibilitySettings { get; private set; } | ||
|
|
||
| [field: SerializeField] | ||
| public GameObject DestinationMarkerPrefab { get; private set; } |
There was a problem hiding this comment.
Inconsistency with codebase pattern: PointAtMarkerPrefab uses AssetReferenceGameObject and is loaded asynchronously via assetsProvisioner.ProvideMainAssetAsync in InitializeAsync. DestinationMarkerPrefab bypasses this entirely with a direct serialized GameObject reference.
This means the prefab is held in memory from startup regardless of whether the feature is used, and it doesn't participate in the asset lifecycle managed by the provisioner. It should follow the same pattern as PointAtMarkerPrefab — unless the intent is to always have it loaded (e.g. it's in the Essentials group), in which case please add a comment explaining why the direct reference is appropriate here.
|
PR #7978, run #23909705745 Builds: Windows change, Windows baseline, macOS change, macOS baseline Intel Core i3
|
Changes public class attributes to private setters and serializable. Changed double click to use Input System double tap Removed programmatic transition of Start to Idle in favor of Exit Time in the animator controller. Moved destionation marker assets into its own folder Broke System update into smaller logic blocks for readability Added a warning log when Destination Marker is not set in the global configuration Used World.AddOrSet Max raycast distance limited to 250. Restored Grass shader
markerShouldBeHidden removed — replaced with entitiesToCancelNavigation (per-frame temp list, cleared at top of Update) World.Remove<PointAndClickMovementComponent> is now deferred — DriveMovement adds to the list, removals happen after the query when all refs are out of scope DestinationMarkerView uses a single shared MaterialPropertyBlock — one SetColor call, then SetPropertyBlock per renderer, no material instances created DestinationMarkerPrefab is now AssetReferenceGameObject, loaded in InitializeAsync via assetsProvisioner, matching the PointAtMarkerPrefab pattern
|
@claude review |
|
Claude finished @olavra's task in 2m 0s —— View job Code Review
All five blocking issues from the previous review have been resolved:
The code is clean and follows codebase conventions. No remaining blocking issues. REVIEW_RESULT: PASS ✅ |
Ludmilafantaniella
left a comment
There was a problem hiding this comment.
QA Result: ✅ Approved
Tested on Windows and Mac.
What was tested:
- Double clicking moves the avatar towards the target point correctly
- Marker appears and disappears after reaching the destination or failing to reach it
- Only one marker visible at a time
- Movement is cancelled when using directional keys (WASD)
- Movement is cancelled when opening menus
- Movement is cancelled when the avatar can't reach the destination due to an obstacle
- Shift to run, Space to jump and glide work correctly during automatic movement
- Multiple rapid double clicks handled correctly
- Tested in Genesis City, personal world and scenes with objects
- Controls menu shows the new double click input option
All PR test steps and edge cases verified. No regressions found.
7978-evi2.mp4
7978-evi.mp4
✅Sanity check performed:
- ✔️ Backpack and wearables in world
- ✔️ Emotes in world and in backpack
- ✔️ Teleport with map/coordinates/Jump In
- ✔️ Chat and multiplayer
- ✔️ Profile card
- ✔️ Camera
- ✔️ Skybox
- ✔️ Settings
alejandro-jimenez-dcl
left a comment
There was a problem hiding this comment.
Approved with a few small requests
| private GameObject targetMarker; | ||
| private DestinationMarkerView targetMarkerView; |
There was a problem hiding this comment.
Nitpicking here, I'd use either Destination or Target, but not both
| if (!hasDoubleClick) | ||
| return; |
There was a problem hiding this comment.
we could avoid passing this param and place the query call inside the hasDoubleClick check in the Update.
sandrade-dcl
left a comment
There was a problem hiding this comment.
Amazing feature, good work!! I only left a comment, please take a look to it.
| @@ -0,0 +1,55 @@ | |||
| using UnityEngine; | |||
|
|
|||
| namespace DCL.AvatarRendering.AvatarShape | |||
There was a problem hiding this comment.
In my opinion DestinationMarkerView.cs doesn't have nothing to do with avatar rendering, I think we should move this class to the CharacterMotion namespace (in fact you have the rest of logic already there).
Pull Request Description
Now you can click anywhere in the world and the avatar will try to reach the destination in a straigh line. A marker determines the target location. You can jump, double jump, glide and shift to run while automatically reaching the destination.
The avatar will stop after a few milliseconds if there is no sustancial increment in movement in the desired direction (cant reach it).
This does not use Navmesh Agents so its pretty simple straight movement, nothing fancy.
Test Instructions