1
\$\begingroup\$

I have a situation where a model is ignored in favour of one behind it. The rear model is returned by EventSystem.current.RaycastAll, and the front model's IPointerClickHandler callback isn't triggered if the rear model is present. The rear model does not implement IPointerClickHandler (or pointer up/down handlers, etc). Both these things work on the front model if the rear model isn't there.

Debugging shows that the Raycast is only returning one result. By comparing behaviour when the rear model is and isn't present, I can verify that the distance value in the RaycastResult is greater when hitting the rear model than when hitting the front model.

I can "fix" the problem by using the Inspector to disable and re-enable the front model.

Here's the problem and the "fix" in action:

Tooltips fixed by disabling and re-enabling an object

Higher quality version here.

EventSystem.current.RaycastAll is used to power the tooltips, and IPointerClickHandler is (unsurprisingly) used to get the cube model to react to clicks.

Update: After more investigation, I've made limited progress:

  • I've fixed the problem when running the game at normal speed by giving both objects a kinematic Rigidbody.
  • However, the problem still occurs when I speed up time. I set Time.timeScale, and increase Time.fixedDeltaTime by the same scale factor as recommended here.
  • I can eliminate the problem by not changing Time.fixedDeltaTime, however I'm reluctant to do so since this has a big impact on framerates at higher speeds (12x being the highest available).
  • If time is paused (i.e. Time.timeScale == 0) then the problem never fixes itself - time needs to be moving forward for the raycast to start hitting the cube. Presumably this is because physics calculations are suspended when time isn't progressing.

enter image description here

Again, higher quality version here

Unity version: 2020.3.11f1

Update 2: As requested, here's the raycast and time scaling code:

public class TooltipDisplay : MonoBehaviour {
    public void FixedUpdate() { // I've tried it in Update too, no change
        PointerEventData pointerData = new PointerEventData(EventSystem.current);
        pointerData.pointerId = -1;
        pointerData.position = Mouse.current.position.ReadValue();
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(pointerData, results);
        Tooltip highest = null;
        foreach (var result in results) {
            // There's only one result here, and it's often the wrong one :(
            Tooltip t = GetTooltip(result.gameObject);
            if (t == null) continue;
            if (highest == null || t.priority > highest.priority) {
                highest = t;
            }
        }
        // If we found a tooltip, display it.
        // ...
        // ...
    }
}


public class SpeedLimiter {
    
    private int multiplier;
    private static readonly float DEFAULT_FIXED_DELTA_TIME = Time.fixedDeltaTime;
    public const float SECONDS_PER_COMMAND = 2.0f;
    public float timeAccumulated { get; private set; }
    
    // Called from a Unity Button press (bottom-right of video) or from an Input system keypress handler.
    public void SetMultiplier(int speed) {
        multiplier = speed;
        Time.timeScale = multiplier;
        Time.fixedDeltaTime = DEFAULT_FIXED_DELTA_TIME * multiplier;
    }

    public bool Advance() { // Called in Update
        bool looped = false;
        timeAccumulated += Time.deltaTime;
        while (timeAccumulated >= SECONDS_PER_COMMAND) {
           timeAccumulated -= SECONDS_PER_COMMAND;
           looped = true;
        }
        return looped;
    }
}


public class UHexahedron : MonoBehaviour {
    Vector3 fromPosition;
    Vector2 toPosition;
    float translationStart;
    float translationDuration;
    bool translating;

    public void FixedUpdate() {
        if (translating) {
            float currentTime = SpeedLimited.timeAccumulated;
            if (currentTime < translationStart) return;
            if (currentTime >= translationStart + translationDuration) {
                Translate(1);
            }
            else {
                float lerp = (currentTime - translationStart) / translationDuration;
                Translate(lerp);
            }
        }
    }
    
    private void Translate(float lerp) {
        if (lerp >= 1) {
            transform.position = toPosition; // Tried rigidbody.position, no change
            translating = false;
            return;
        }
        transform.position = Vector3.lerp(fromPosition, toPosition, lerp); // Again, tried rigidbody.position, no change.
    }
}
New contributor
Tarrenam is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
4
  • \$\begingroup\$ How are you moving these objects? With transform.position? That leaves their physics representation behind until the next physics step has a chance to match back up, which happens less often with respect to game time when you increase fixedDeltaTime. So the body might not be there yet when the pointer move is handled. Have you tried moving these objects with their rigidbodies, or using SyncTransforms to ensure the latest transform positions are pushed to the colliders in time to process the pointer movements accurately? Also, can you show your RaycastAll code and when you call it? \$\endgroup\$ – DMGregory yesterday
  • \$\begingroup\$ I've tried SyncTransforms, that didn't help. I could try moving the rigidbodies instead. The thing that's confusing me is that the scaling of fixedDeltaTime is to get the physics interval back to 20ms of real time, but the tooltips take much longer than that to update. \$\endgroup\$ – Tarrenam yesterday
  • \$\begingroup\$ We need to see a Minimal Complete Verifiable Example. Not just these 7 lines, but also where they are called, and where you alter your time scale, since all of these pieces appear to be related to the problem. \$\endgroup\$ – DMGregory yesterday
  • \$\begingroup\$ I've added the code that handles changing time scaling and cube movement (with comments showing other things I've tried). I tried switching to Rigidbody.position, that didn't help, sadly. \$\endgroup\$ – Tarrenam yesterday

Your Answer

Tarrenam is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.