protected void DoRaycast(Transform origin)
    {
        RaycastHit hit;
        Quaternion angleBias        = GetFireBiasQuaternion(origin);
        Vector3    emitPosition     = origin.position;
        Vector3    towardsDirection = angleBias * origin.forward;

        Debug.DrawRay(origin.position, towardsDirection, Color.red);

        if (Physics.Raycast(emitPosition, towardsDirection, out hit, range, mask))
        {
            // Debug.DrawRay(emitPosition, towardsDirection, Color.red, 2f);
            if (hit.collider != null)
            {
                Debug.DrawLine(emitPosition, hit.point, Color.magenta, 2f);
                // === Debug only ===
                // GameObject debugHitpointObject = Instantiate(debugHitPointPrefab, hit.point, Quaternion.Euler(Vector3.zero));
                // Destroy(debugHitpointObject, 1.0f);

                // Try to inflict some damage
                float damage = DamageInflictUtil.DamageLerp(maxDamage, minDamage,
                                                            Vector3.Distance(hit.point, origin.position), damageDecayRatio * range, range);

                DamageInflictUtil.TryInflictDamage(hit, owner.gameObject, damage, inflictForce);
            }
        }
        RenderRay(hit, origin);
    }
    void Update()
    {
        // Correct trajectory
        float timeSpent = Time.time - this.createdTime;

        if (timeSpent < trajectionCorrectionTime)
        {
            transform.Translate(trajectoryCorrectionVector * Time.deltaTime * (1 / trajectionCorrectionTime), Space.Self);
        }

        // Update position
        transform.Translate(speed * transform.forward * Time.deltaTime, Space.World);
        distanceTravelled += speed * Time.deltaTime;

        // Self-destruct if out of range.
        if (distanceTravelled > range)
        {
            Destroy(this.gameObject);
        }
        // Hit detection.
        RaycastHit hit;

        if (Physics.Raycast(transform.position, transform.forward, out hit, speed * Time.deltaTime, damageMask))
        {
            float damage = DamageInflictUtil.DamageLerp(maxDamage, minDamage, distanceTravelled, damageDecayRange, range);
            DamageInflictUtil.TryInflictDamage(hit, owner, damage, inflictForce);
            Destroy(this.gameObject);
        }
    }