0
\$\begingroup\$

When I press play my character controller turns black, the scale on the z axis is 0 and all the children are not visible. Now the thing this only happens when I press play — if I don't, everything is fine in my scene and game view.

Player (Parent object) enter image description here

Player move script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    public CharacterController controller;
    public float gravity = -30;
    public float sphereRadius = 0.2f;
    public Transform groundCheck;
    public LayerMask groundMask;
    public float jumpHeight = 3f;
    public float sprintSpeed = 20f;
    public float walkSpeed = 15f;
    public float crouchHeight = 0.5f;
    public float crouchSpeed;
    public float startHeight;

    private Vector3 velocity;
    private bool isGrounded = true;
    private float speed;

    private void Start() {
        velocity.y = 0f;
        speed = walkSpeed;
        crouchSpeed = speed / 2;
        startHeight = transform.localScale.y;
    }

    // Update is called once per frame
    private void Update()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, sphereRadius, groundMask);

        float x = Input.GetAxisRaw("Horizontal");
        float z = Input.GetAxisRaw("Vertical");

        Vector3 move = transform.right * x + transform.forward * z;
        controller.Move(move.normalized * speed * Time.deltaTime);

        if (velocity.y < -0.35f)
        {
            velocity.y = -0.35f;
        }

        // Jumping and crouching
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            velocity.y = jumpHeight;
        } else if (Input.GetKey(KeyCode.LeftShift)) {
            speed -= 7.5f;
            transform.localScale = new Vector3(transform.localScale.x, crouchHeight, transform.localRotation.z);
        } else if (!Input.GetKey(KeyCode.LeftShift)) {
            speed = walkSpeed;
            transform.localScale = new Vector3(transform.localScale.x, startHeight, transform.localRotation.z);
        }

        // Sprinting
        if (Input.GetKey(KeyCode.LeftControl))
        {
            speed = sprintSpeed;
        }
        else if (!Input.GetKey(KeyCode.LeftControl))
        {
            speed = walkSpeed;
        }

        velocity.y += gravity * Time.deltaTime * Time.deltaTime;
        controller.Move(velocity);
    }
}

Player script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public float health = 100f;

    public void TakeDamage(float amount)
    {
        health -= amount;
        if (health <= 0)
            Destroy(gameObject);
    }
}

Main Camera object enter image description here

Camera look script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraLook : MonoBehaviour
{
    public float sensitivity = 100f;
    public Transform playerBody;
    
    private float xRotation;

    private void Start() {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    // Update is called once per frame
    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -90f, 90f);

        transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
        playerBody.Rotate(Vector3.up * mouseX);
    }
}

Hierarchy enter image description here

Here is a comparison for when I am playing versus when not:

not playing not playing

playing enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ I notice you're passing localRotation.z as the z component of your localScale, which does not make much sense. Did you mean to use scale here, not rotation? \$\endgroup\$
    – DMGregory
    Commented Oct 11, 2022 at 5:48
  • \$\begingroup\$ Thanks a lot now I feel silly for not noticing that. Anyways thanks! It worked! \$\endgroup\$ Commented Oct 11, 2022 at 9:21

1 Answer 1

0
\$\begingroup\$

When you see an object flatten, your first step should be to check whether anything is setting its transform scale properties (or its parent's/grandparent's/etc.).

That leads us to these lines:

} else if (Input.GetKey(KeyCode.LeftShift)) {
    speed -= 7.5f;
    transform.localScale = new Vector3(transform.localScale.x, crouchHeight, transform.localRotation.z);
} else if (!Input.GetKey(KeyCode.LeftShift)) {
    speed = walkSpeed;
    transform.localScale = new Vector3(transform.localScale.x, startHeight, transform.localRotation.z);
}

Note that the x component of the new scale is set to the x component of the old scale,
but the z component of the new scale is set to the z component of the rotation quaternion!

This isn't anything geometrically meaningful - a quaternion's xyz components are imaginary numbers representing the sine of half the angle of rotation times the unit axis, so they don't make sense to use as scale factors. In particular, for a character controller that only ever rotates in yaw, we expect only the y and w components of the quaternion to have non-zero values, leading to flattening when the z=0 component is used as a scale.

This was probably an error caused by hasty acceptance of an auto-complete suggestion, coupled with the fact that the line is long so the offending "rotation" part of the name might have scrolled out of view while you were hunting for the bug.

Try a pattern like this instead - it's less typing, clearer about your intention, and not so prone to hidden bugs:

// Copy the scale to a stack variable (no GC allocation, don't worry!)
var scale = transform.localScale;
// Modify only the part you want to change.
scale.y = startheight;
// Re-assign it.
transform.localScale = scale;

You can also, if you want, make a little extension method to streamline this type of operation:

public static class VectorExtensions {
    public Vector3 ReplaceY (this Vector3 v, float y) {
        v.y = y;
        return v;
    }
    // Repeat for x, z...
}

Then this becomes a one-liner that won't scroll out of your reading column:

transform.localScale = transform.localScale.ReplaceY(startHeight);
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .