Sorry for my title, I’m at my wit’s end lol. I don’t know what happened, I had this script working just fine, I changed the whole system for movement, realized it wasn’t working, so changed it back. I don’t know why, but I broke the upward movement.
It’s a mobile game where you run along a path collecting potions and you use those potions to make stairs and rise to avoid objects. I was just increasing the rb.position at first, but it didn’t look very smooth so I changed it to a new system where it smoothly increased the moveGoal’s y position.
Here’s my script,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using PathCreation;
public class Player : MonoBehaviour
{
bool canPlaceStair = true, knockBack, levelOver, dead, reachedEndOfLevel, placingStairs, initialized;
bool reachedStairs;
Rigidbody rb;
float speed = 3;
[SerializeField] float baseSpeed = 10, endSpeed = 5f, knockBackForce = 500, verticalKnockback = 2, distanceToWaypoint = 1f;
[SerializeField] float rotationSpeed = 3;
[SerializeField] int maxMana = 100, stairPoolCount = 100;
int manaCount, health = 3;
[SerializeField] GameObject stairDrop;
[SerializeField] Transform stairSpawner;
List<Transform> stairPool;
[SerializeField] float distanceToRise = .5f, stairPlaceTimerSet = 0.1f, knockBackTimerSet = 1f, endStairTimerSet = 0.05f;
float stairPlaceTimer,knockBackTimer;
int currentWaypointIndex;
[SerializeField] Transform waypointHolder;
Transform stairHolder;
Transform[] waypoints;
[SerializeField] Color hurtColour;
Color defaultColour = Color.white;
SkinnedMeshRenderer playerRenderer;
Vector3 moveGoal;
Quaternion rotGoal;
[SerializeField]Slider manaBar;
private void Awake()
{
playerRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
speed = baseSpeed;
}
private void Start()
{
rotGoal = transform.rotation;
stairHolder = GameObject.Find("StairHolder").transform;
rb = GetComponent<Rigidbody>();
stairPlaceTimer = stairPlaceTimerSet;
StartCoroutine(DelayToAddWaypoints());
GameManager.gm.PauseAction += GamePaused;
GameManager.gm.UnPauseAction += GameUnpaused;
manaBar.maxValue = maxMana;
stairPool = PopulatePool();
}
IEnumerator DelayToAddWaypoints()
{
yield return null;
waypoints = new Transform[waypointHolder.childCount];
for (int i = 0; i < waypoints.Length; i++)
{
waypoints[i] = waypointHolder.GetChild(i);
}
moveGoal = GetMoveGoal(waypoints[0]);
initialized = true;
}
List<Transform> PopulatePool()
{
List<Transform> poolList = new List<Transform>();
for (int i = 0; i < stairPoolCount; i++)
{
Transform stair = Instantiate(stairDrop,Vector3.zero,Quaternion.identity,stairHolder).transform;
poolList.Add(stair);
stair.gameObject.SetActive(false);
}
return poolList;
}
PlacedStair GetStair()
{
PlacedStair stairToGet = null;
for (int i = 0; i < stairPool.Count; i++)
{
if (!stairPool[i].gameObject.activeInHierarchy)
{
stairToGet = stairPool[i].GetComponent<PlacedStair>();
return stairToGet;
}
}
stairToGet = Instantiate(stairDrop, Vector3.zero, Quaternion.identity, stairHolder).GetComponent<PlacedStair>();
stairPool.Add(stairToGet.transform);
return stairToGet;
}
private void Update()
{
if (Input.touchCount > 0 || Input.GetKey(KeyCode.Space))
{
if (GameManager.gm.paused) GameManager.gm.UnPauseAction();
else if (manaCount > 0 && canPlaceStair && !knockBack && !levelOver && !reachedEndOfLevel)
{
canPlaceStair = false;
SpawnBrick();
}
}
if (stairPlaceTimer > 0 && !canPlaceStair)
{
stairPlaceTimer -= Time.deltaTime;
}
else if(stairPlaceTimer <= 0)
{
canPlaceStair = true;
}
if (knockBack)
{
if(knockBackTimer > 0)
{
knockBackTimer -= Time.deltaTime;
}
else if(knockBack && !dead)
{
foreach (Material mat in playerRenderer.materials)
{
mat.color = defaultColour;
}
knockBack = false;
rb.velocity = Vector3.zero;
GetComponent<Collider>().isTrigger = false;
}
}
if (!rb.useGravity)
{
if (reachedEndOfLevel)
{
rb.useGravity = true;
}
if (Input.touchCount == 0 && !Input.GetKey(KeyCode.Space))
{
rb.useGravity = true;
placingStairs = false;
speed = baseSpeed;
}
else if(manaCount < 1)
{
rb.useGravity = true;
placingStairs = false;
speed = baseSpeed;
}
}
}
void FixedUpdate()
{
if (rb.position.y < -20 && !dead) Death();
if (!knockBack && !levelOver && !dead && initialized)
{
if (Mathf.Abs(rb.position.x - moveGoal.x) > distanceToWaypoint || Mathf.Abs(rb.position.z - moveGoal.z) > distanceToWaypoint)
{
moveGoal = GetMoveGoal(waypoints[currentWaypointIndex]);
moveGoal.y = rb.position.y;
if (placingStairs)
{
if (reachedStairs)
{
moveGoal.y = waypoints[currentWaypointIndex].position.y;
}
else
{
moveGoal.y += distanceToRise;
}
}
rb.position = Vector3.MoveTowards(rb.position, new Vector3(moveGoal.x,moveGoal.y,moveGoal.z), speed * Time.deltaTime);
}
else
{
if (currentWaypointIndex < waypoints.Length - 1)
{
currentWaypointIndex++;
if (!levelOver && initialized)
{
moveGoal = GetMoveGoal(waypoints[currentWaypointIndex]);
Vector3 dir = ((moveGoal - transform.position).normalized);
rotGoal = Quaternion.LookRotation(dir);
}
}
else
{
reachedEndOfLevel = true;
}
}
if (transform.rotation != rotGoal)
{
transform.rotation = Quaternion.Lerp(transform.rotation, rotGoal, rotationSpeed * Time.deltaTime);
}
}
}
void SpawnBrick()
{
if (reachedStairs && speed != endSpeed) speed = endSpeed;
placingStairs = true;
if(rb.useGravity)rb.useGravity = false;
manaCount--;
manaBar.value = manaCount;
PlacedStair stair = GetStair();
stair.gameObject.SetActive(true);
stair.transform.position = stairSpawner.position + transform.right * 2;
stair.moveGoal = stairSpawner.position;
stair.transform.rotation = transform.rotation;
stairPlaceTimer = stairPlaceTimerSet;
rb.velocity = Vector2.zero;
}
Vector3 GetMoveGoal(Transform trans)
{
if (waypoints.Length < 1 || trans == null) return transform.position;
Vector3 goal;
goal.x = trans.position.x;
goal.z = trans.position.z;
goal.y = rb.position.y;
return goal;
}
private void OnTriggerEnter(Collider trigger)
{
if(trigger.GetComponent<IPickup>() != null)
{
trigger.GetComponent<IPickup>().PickUp();
}
if (trigger.tag == "EndGoal" && !levelOver)
{
ReachGoal(trigger.transform.parent);
}
}
private void OnCollisionEnter(Collision collision)
{
if(collision.collider.tag == "Obstacle")
{
KnockBack(collision.collider.transform);
}
}
void KnockBack(Transform obstacle)
{
foreach(Material mat in playerRenderer.materials)
{
mat.color = hurtColour;
}
ChangeMana(-10);
knockBack = true;
knockBackTimer = knockBackTimerSet;
Vector3 knockBackDir = Vector3.zero;
knockBackDir = ((-transform.forward).normalized + Vector3.up * verticalKnockback) * knockBackForce;
GetComponent<Collider>().isTrigger = true;
rb.AddForce(knockBackDir);
health--;
if (health <= 0)
Death();
}
void Death()
{
GetComponent<Collider>().enabled = false;
Camera.main.GetComponent<CameraMovement>().disabled = true;
canPlaceStair = false;
dead = true;
GameManager.gm.GameOver();
}
private void OnDrawGizmos()
{
waypoints = new Transform[waypointHolder.childCount];
for (int i = 0; i < waypoints.Length; i++)
{
waypoints[i] = waypointHolder.GetChild(i);
}
for (int i = 0; i < waypoints.Length; i++)
{
Gizmos.color = Color.red;
if (i > 0) Gizmos.DrawLine(waypoints[i - 1].position, waypoints[i].position);
Gizmos.color = Color.yellow;
Gizmos.DrawSphere(waypoints[i].position, 0.5f);
}
}
void ReachGoal(Transform endT)
{
transform.position = endT.position + Vector3.up * endT.localScale.y / 2;
levelOver = true;
GetComponent<Animation>().Stop();
canPlaceStair = false;
GameManager.gm.EndLevel();
rb.isKinematic = true;
manaBar.gameObject.SetActive(false);
}
public void ChangeMana(int manaValue)
{
manaCount += manaValue;
manaCount = Mathf.Clamp(manaCount, 0, maxMana);
manaBar.value = manaCount;
}
void GamePaused()
{
canPlaceStair = false;
}
void GameUnpaused()
{
if(stairPlaceTimer <= 0)
{
canPlaceStair = true;
}
}
public void PassEnd()
{
distanceToRise = 0;
reachedStairs = true;
stairPlaceTimerSet = endStairTimerSet;
}
}
So, the fixed update is what we’re looking at, in the SpawnBrick method, it sets the placing stair bool to true, and if that bool is true, the fixed update increases the y position. it’s also setting the movegoal’s y position to the rb.position.y to make sure it doesn’t keep increasing. But this is creating some really weird bugs, for one it will barely move forward at all when it’s rising. I don’t know why this is, it’s only adding to the y value of the moveGoal, not changing any of the other values…
Can someone help me figure this out? I know there’s some weird artifacts in my code, as I was trying a lot of different things to fix this, mainly we’re looking at line 178 to 201.
Thanks.
Edit: Solved, I don’t know why every time I make a post after trying for hours and failing, I end up fixing it, I also don’t know why this is a fix, it even seems kinda ineffecient, but if anyone knows a better way, I’m all ears… I replaced the
rb.position = Vector3.MoveTowards(rb.position, new Vector3(moveGoal.x,moveGoal.y,moveGoal.z), speed * Time.deltaTime);
with instead, a new vector3 with individual values being set with Mathf.MoveTowards. Is this because vector3.MoveTowards averages out the values or something? I don’t understand it lol