Intermediate - weird transform/raycast/particleSystem issue. Save me!

Hey guys! Any suggestions for a solution is more than welcome.

My issue is fairly simple but I’m uploading everything connected to the issue just in case. I also hope I’m making sense here (english is not my first language).

  • I’m instantiating a prefab (attached “hierarchy cutout”)
  • the RayCaster casts a ray to find any enemy directly in front of the player (pink capsule).
  • The RayCaster then moves the DetonationObject to the raycast hitPoint (or 30 points along the z-axis.
  • ParticleEmitter is called by the DetonationObject in “InitializeParticleSystem”.

For some doggone reason the RayCaster refuse to cast straight ahead (Vector3.forward) and tilts the ray. It is essential here that the tilt perfectly correlates with player position on the y-axis. Also the y-value differential between “relativeHitPos” and Player is almost exactly the same as the y-value differential between Player and origo (attached GameView2). Lastly as you can see the actual particles are rendered way above the ray.

I can’t find anything strange in the code. It looks like a scaling issue to me but all transforms are zero and the Instantiation does not assign a parent to the prefab. Can it be part of the particleSystem-component it self? I KNOW this is obvious to someone but I’m oblivious after several hours.

Instantiation of prefab “Particle1”

Instantiate(projectiles.Items[preppedWeapon], transform.position, Quaternion.identity);

RayCaster:

    private void CastRay()
    {
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hitData;

        if (Physics.Raycast(ray, out hitData, 30, layerMask))
        {
            Vector3 hitPos = hitData.collider.gameObject.transform.position;
            Vector3 relativeHitPos =  transform.position + hitPos;

            Debug.DrawRay(transform.position, relativeHitPos, Color.blue, 2);

            StartCoroutine(ActivateDetonationObject(relativeHitPos));
        }
        else
        {
            Debug.DrawRay(transform.position, new Vector3(transform.position.x,
                transform.position.y, transform.position.z + 30), Color.blue, 2);

            StartCoroutine(ActivateDetonationObject(new Vector3(transform.position.x,
                transform.position.y, transform.position.z + 30)));
        }
    }

    private IEnumerator ActivateDetonationObject(Vector3 moveTo)
    {
        detonationObject.transform.Translate(moveTo);
        detonationObject.SetActive(true);

        yield return new WaitForFixedUpdate();

        //Debug option.
        //yield return new WaitForSeconds(2);

        detonationObject.SetActive(false);
        detonationObject.transform.Translate(transform.position);
    }

ParticleEmitter:

public void InitiateParticleSystem(Vector3 endPos)
    {
        startPosition = transform.position;
        endPosition = endPos;

        Vector3 particlePosition = (endPosition - startPosition) / 2 + startPosition;
        float distance = Vector3.Distance(endPosition, startPosition) / 2;
        int numParticles = (int)distance * 100;
        particleSystem.transform.LookAt(endPosition);
        ParticleSystem.ShapeModule sm = particleSystem.shape;
        sm.position = particlePosition;
        sm.radius = distance;

        ParticleSystem.EmissionModule em = particleSystem.emission;
        em.rateOverTime = numParticles;

        particleSystem.Play();
    }


8179415--1065164--HierarchyCutout.png

What I don’t understand is:
A) What do you want your program to do?
B) What does it do instead?
C) How you calculate a relative position → Vector3 relativeHitPos = transform.position + hitPos; Shouldn’t this be Vector3 relativeHitPos = hitPos - transform.position; ?

Also for readability I suggest changing this

           Debug.DrawRay(transform.position, new Vector3(transform.position.x,
                transform.position.y, transform.position.z + 30), Color.blue, 2);

           StartCoroutine(ActivateDetonationObject(new Vector3(transform.position.x,
                transform.position.y, transform.position.z + 30)));

To this:

           Vector3 targetPos = transform.position;
           targetPos.z += 30;

           Debug.DrawRay(targetPos, Color.blue, 2);

           StartCoroutine(ActivateDetonationObject(targetPos));

also you can read the Transform directly from the raycastHit
Unity - Scripting API: RaycastHit.transform

So you can change
Vector3 hitPos = hitData.collider.gameObject.transform.position;
to
Vector3 hitPos = hitData.transform.position;

Big thanks for replying!

A) I want the raycast to find a position directly .forward of the raycaster. That’s it basically! Really basic stuff that doesn’t work for me.
B) Instead I get this angled raycast that I don’t understand.
C) Strangely enough. That change in code made no difference to the behaviour. That surely is a clue…

Edit: clarification.
A) To raycast from the RayCaster and find a collider directly .forward of the RayCaster.transform.position or (if no collider is found) a point 30 units along the z-axis. Then move DetonationObject to that point.

Thanks for the input. It’s a lot cleaner.

So it turn out setting the position of a particle system shape module isn’t actually setting the position. Instead it is setting an offset to the current position.

Rewriting the RayCaster and adding a line “particlePosition.y = 0;” to the ParticleEmitter solved the issue.

    private void CastRay()
    {
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hitData;

        if (Physics.Raycast(ray, out hitData, 30, layerMask))
        {
            IDamageable hit = hitData.transform.GetComponent<IDamageable>();

            if (hit == null)
            {
                hitPoint = new Vector3(transform.position.x, transform.position.y,
                    transform.position.z + 30);

                particleEmitter.InitiateParticleSystem(hitPoint);
            }
            else
            {
                hit.Damage(doDamage);
                hitPoint = hitData.transform.position;
                particleEmitter.InitiateParticleSystem(hitPoint);
            }
        }
        else
        {
            hitPoint = new Vector3(transform.position.x, transform.position.y,
                    transform.position.z + 30);

            particleEmitter.InitiateParticleSystem(hitPoint);
        }
    }
    public void InitiateParticleSystem(Vector3 endPos)
    {
        startPosition = transform.position;

        Vector3 particlePosition = (endPos - startPosition) / 2 + startPosition;
        float distance = Vector3.Distance(endPos, startPosition) / 2;
        int numParticles = (int)distance * 100;
        particleSystem.transform.LookAt(endPos);
        ParticleSystem.ShapeModule sm = particleSystem.shape;
        particlePosition.y = 0;
        sm.position = particlePosition;
        sm.radius = distance;

        ParticleSystem.EmissionModule em = particleSystem.emission;
        em.rateOverTime = numParticles;

        particleSystem.Play();
    }