Forum begins after the advertisement:
[Part 6] Magnet problem
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 6] Magnet problem
- This topic has 7 replies, 2 voices, and was last updated 9 months, 3 weeks ago by Terence.
-
AuthorPosts
-
December 12, 2023 at 2:16 pm #12585::
I have followed all the tutorials, but i still found the problem about magnet: the experience gem fly away when player change the direction.
December 12, 2023 at 3:29 pm #12589::Hi g Dni,
Update 13 December 2023: The code below doesn’t work. I’ve posted a new one below.
This is something that I will address in a future part. In the meantime, you can apply these changes to the
PlayerCollector.cs
script to fix this:using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCollector : MonoBehaviour { PlayerStats player; CircleCollider2D playerCollector; public float pullSpeed; Rigidbody rb; private void Start() { player = FindObjectOfType<PlayerStats>(); playerCollector = GetComponent<CircleCollider2D>(); } void Update() { playerCollector.radius = player.Magnet; List
toRemove = new List<int>(); if(rb) { //Vector2 pointing from the item to the player Vector2 forceDirection = (transform.position - attractedRigidbodies[i].transform.position).normalized; //Applies force to the item in the forceDirection with pullSpeed attractedRigidbodies[i].AddForce(forceDirection * pullSpeed); } } void OnTriggerEnter2D(Collider2D col) { //Check if the other game object has the ICollectible interface if (col.gameObject.TryGetComponent(out ICollectible collectible)) { //Pulling animation //Gets the Rigidbody2D component on the itemRigidbody2Drb = col.gameObject.GetComponent<Rigidbody2D>();//Vector2 pointing from the item to the player Vector2 forceDirection = (transform.position - col.transform.position).normalized; //Applies force to the item in the forceDirection with pullSpeed rb.AddForce(forceDirection * pullSpeed);//If it does, call the OnCollect method collectible.Collect(); } } }The issue with the script is that the force to move the collectible is not updated if you change directions. By moving it to
Update()
, it will cause the collectible to constantly update every frame, so it always tracks the player.December 13, 2023 at 10:37 am #12630::There is problem cuz we haven’t declare the “col” variable in Update().
Assets/Scripts/Player/PlayerCollector.cs(25,60): error CS0103: The name 'col' does not exist in the current context
December 13, 2023 at 11:49 am #12632::Hi g Dni,
Update 14 December 2023: Unfortunately, the code below doesn’t work as well. An edited version is available further down below.
You are right that the code doesn’t work because
col
is undefined inUpdate()
. I have made some corrections to the code. Let me know if it works.using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCollector : MonoBehaviour { PlayerStats player; CircleCollider2D playerCollector; public float pullSpeed; List<Rigidbody2D> attractedRigidbodies = new List<Rigidbody2D>(); private void Start() { player = FindObjectOfType<PlayerStats>(); playerCollector = GetComponent<CircleCollider2D>(); } void Update() { playerCollector.radius = player.Magnet; List<int> toRemove = new List<int>(); for(int i = 0; i < attractedRigidbodies.Count; i++) { // Before we start doing anything, we check for null values in our array, which // is caused by our GameObjects being deleted when they are collected. // We also have to call continue, otherwise attractedRigidbodies[i] being null can cause // NullReferenceException errors. if(attractedRigidbodies[i] == null) { toRemove.Add(i); continue; } //Vector2 pointing from the item to the player Vector2 forceDirection = (transform.position - attractedRigidbodies[i].transform.position).normalized; //Applies force to the item in the forceDirection with pullSpeed attractedRigidbodies[i].AddForce(forceDirection * pullSpeed); } // Remove all null objects in our attracted rigidbodies. foreach(int i in toRemove) attractedRigidbodies.RemoveAt(i); } void OnTriggerEnter2D(Collider2D col) { //Check if the other game object has the ICollectible interface if (col.gameObject.TryGetComponent(out ICollectible collectible)) { //Pulling animation
//Gets the Rigidbody2D component on the item Rigidbody2D rb = col.gameObject.GetComponent<Rigidbody2D>();// Adds the collected object's Rigidbody to our list, so we can pull it in Update(). attractedRigidbodies.Add(col.gameObject.GetComponent<Rigidbody2D>());//Vector2 pointing from the item to the player Vector2 forceDirection = (transform.position - col.transform.position).normalized; //Applies force to the item in the forceDirection with pullSpeed rb.AddForce(forceDirection * pullSpeed);//If it does, call the OnCollect method collectible.Collect(); } } }Here’s my explanation for the code: If we want the collector to be accurate, we will need to run the code on
Update()
though, so we will need to create the ListattractedRigidbodies
in the class to track all the objects that are currently being attracted. Every time we get in range to attract something, its rigidbody will be added toattractedRigidbodies
.In
Update()
, we simply update the velocity of all attracted rigidbodies. We also need to remove all rigidbodies in the list that are null, beacuse after an object is collected, the GameObject gets destroyed, and we have to update the list accordly.December 13, 2023 at 2:09 pm #12638::Hi Terence,
Thank u for replying. Unfortunately,it still have problems. When player walked close to the gem, experience increased but the gem never been destroyed. And the animation still missing.
December 13, 2023 at 6:56 pm #12642December 14, 2023 at 12:33 pm #12652::g Dni,
I’ve made a couple of fixes to the code after testing it and it works. There were a few syntax errors and an issue where the pickup accelerated towards the player every frame. The changes are highlighted below.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCollector : MonoBehaviour { PlayerStats player; CircleCollider2D playerCollector; public float pullSpeed; List<Rigidbody2D> attractedRigidbodies = new List<Rigidbody2D>(); private void Start() { player = FindObjectOfType<PlayerStats>(); playerCollector = GetComponent<CircleCollider2D>(); } void Update() { playerCollector.radius = player.Magnet; List<int> toRemove = new List<int>(); for(int i = 0; i < attractedRigidbodies.Count; i++) { // Before we start doing anything, we check for null values in our array, which // is caused by our GameObjects being deleted when they are collected. // We also have to call continue, otherwise attractedRigidbodies[i] being null can cause // NullReferenceException errors. if(attractedRigidbodies[i] == null) {
//toRemove.Add(i);continue; } //Vector2 pointing from the item to the player Vector2 forceDirection = (transform.position - attractedRigidbodies[i].transform.position).normalized; //Applies force to the item in the forceDirection with pullSpeed attractedRigidbodies[i].AddForce(forceDirection * pullSpeed); }// Remove all null objects in our attracted rigidbodies. //foreach(int i in toRemove) attractedRigidbodies.RemoveAt(i);attractedRigidbodies.Clear(); } void OnTriggerEnter2D(Collider2D col) { //Check if the other game object has the ICollectible interface if (col.gameObject.TryGetComponent(out ICollectible collectible)) { //Pulling animation // Adds the collected object's Rigidbody to our list, so we can pull it in Update(). attractedRigidbodies.Add(col.gameObject.GetComponent<Rigidbody2D>()); //If it does, call the OnCollect method collectible.Collect(); } } }Can you try this again and see if it works?
January 30, 2024 at 12:24 pm #13199::Found another problem with the code:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerCollector : MonoBehaviour { PlayerStats player; CircleCollider2D playerCollector; public float pullSpeed; List<Rigidbody2D> attractedRigidbodies = new List<Rigidbody2D>(); private void Start() { player = FindObjectOfType<PlayerStats>(); playerCollector = GetComponent<CircleCollider2D>(); } void Update() { playerCollector.radius = player.Magnet; List<int> toRemove = new List<int>(); for(int i = 0; i < attractedRigidbodies.Count; i++) { // Before we start doing anything, we check for null values in our array, which // is caused by our GameObjects being deleted when they are collected. // We also have to call continue, otherwise attractedRigidbodies[i] being null can cause // NullReferenceException errors. if(attractedRigidbodies[i] == null) { //toRemove.Add(i); continue; } //Vector2 pointing from the item to the player Vector2 forceDirection = (transform.position - attractedRigidbodies[i].transform.position).normalized; //Applies force to the item in the forceDirection with pullSpeed
attractedRigidbodies[i].AddForce(forceDirection * pullSpeed);attractedRigidbodies[i].velocity = forceDirection * pullSpeed; } // Remove all null objects in our attracted rigidbodies. //foreach(int i in toRemove) attractedRigidbodies.RemoveAt(i); attractedRigidbodies.Clear(); } void OnTriggerEnter2D(Collider2D col) { //Check if the other game object has the ICollectible interface if (col.gameObject.TryGetComponent(out ICollectible collectible)) { //Pulling animation // Adds the collected object's Rigidbody to our list, so we can pull it in Update(). attractedRigidbodies.Add(col.gameObject.GetComponent<Rigidbody2D>()); //If it does, call the OnCollect method collectible.Collect(); } } } -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: