Forum begins after the advertisement:
[General] Pick up modification – push and pull!
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [General] Pick up modification – push and pull!
- This topic has 3 replies, 3 voices, and was last updated 1 week, 5 days ago by
Terence.
-
AuthorPosts
-
April 28, 2025 at 12:18 am #18056::
Hello guys,
Apologies if this has already been covered. I am only on video 12 at the moment.
I have been playing with the player collector and pick up scripts to mimic something close to VS in which the pick ups push away from the character then pull in tightly.
To achieve this:
PlayerCollector.CS
using UnityEngine; public class PlayerCollector : MonoBehaviour { PlayerStats player; CircleCollider2D playerCollector; public float pullSpeed; public float initialPushForce = 5f; void Start() { player = FindFirstObjectByType<PlayerStats>(); playerCollector = GetComponent<CircleCollider2D>(); } void Update() { playerCollector.radius = player.CurrentMagnet; } void OnTriggerEnter2D(Collider2D col) { if (col.gameObject.TryGetComponent(out ICollectible collectible)) { if (col.gameObject.TryGetComponent(out Pickup pickup)) { if (!pickup.hasBeenPushed) { Rigidbody2D rb = col.gameObject.GetComponent<Rigidbody2D>(); Vector2 forceDirection = (col.transform.position - transform.position).normalized; rb.AddForce(forceDirection * initialPushForce, ForceMode2D.Impulse); collectible.Collect(); pickup.MarkAsPushed(transform); } } } } }
Pickup.CS
using System; using UnityEngine; public class Pickup : MonoBehaviour, ICollectible { protected bool hasBeenCollected = false; public bool hasBeenPushed = false; private bool isFollowingPlayer = false; private Transform playerTransform; private Rigidbody2D rb; private float followSpeed = 10f; private float pushForce = 6f; private float delayBeforeFollow = 0.1f; void Awake() { rb = GetComponent<Rigidbody2D>(); } public virtual void Collect() { hasBeenCollected = true; } public void MarkAsPushed(Transform player) { hasBeenPushed = true; playerTransform = player; Vector2 forceDirection = (transform.position - player.position).normalized; rb.AddForce(forceDirection * pushForce, ForceMode2D.Impulse); Invoke(nameof(StartFollowingPlayer), delayBeforeFollow); } private void StartFollowingPlayer() { isFollowingPlayer = true; rb.linearVelocity = Vector2.zero; rb.bodyType = RigidbodyType2D.Kinematic; } void Update() { if (isFollowingPlayer && playerTransform != null) { transform.position = Vector2.MoveTowards(transform.position, playerTransform.position, followSpeed * Time.deltaTime); } } private void OnTriggerEnter2D(Collider2D col) { if (col.CompareTag("Player")) { Destroy(gameObject); } } }
Let me know what you think and if you can see any improvements to make to my code.
Thanks, Nathaniel
April 28, 2025 at 12:25 am #18057::Hi Nathaniel,
Your code looks solid and well-structured for the functionality you’re aiming to achieve! Here are a few suggestions and improvements you might consider:
-
Separation of Concerns: Consider separating the logic of collecting pickups and the logic of applying forces into different methods or classes. This can make your code cleaner and easier to maintain.
-
Force Application: Instead of directly using
AddForce
in yourOnTriggerEnter2D
method, you could create a method in yourPickup
class to handle the push away logic. This way, you can encapsulate the behavior of the pickup on being pushed. -
Use of Enum for States: Instead of using boolean flags (
hasBeenCollected
,hasBeenPushed
), you could use an enum to represent the state of the pickup. This can help you manage the states more clearly and avoid potential bugs. -
Pooling Mechanism: If you plan to have many pickups in your game, consider implementing an object pooling mechanism instead of destroying and instantiating pickups. This can improve performance.
-
Physics Settings: Ensure that the physics settings (like gravity, drag) for your Rigidbody2D components are configured in a way that suits your game’s requirements. Sometimes, tweaking these values can yield better results for movement and interactions.
-
Debugging: Add some debug logs to help track the state of your pickups during gameplay. This can be useful for troubleshooting issues when a pickup doesn’t behave as expected.
-
Visual Feedback: Consider providing visual feedback when a pickup is collected or pushed away. This could be done with animations or sound effects to enhance player experience.
Here’s a small code snippet to illustrate how you might refactor the push logic:
// In Pickup class public void PushAway(Transform player, float pushForce) { Vector2 forceDirection = (transform.position - player.position).normalized; rb.AddForce(forceDirection * pushForce, ForceMode2D.Impulse); MarkAsPushed(player); } // In PlayerCollector class void OnTriggerEnter2D(Collider2D col) { if (col.gameObject.TryGetComponent(out ICollectible collectible)) { if (col.gameObject.TryGetComponent(out Pickup pickup) && !pickup.hasBeenPushed) { pickup.PushAway(transform, initialPushForce); collectible.Collect(); } } }
This keeps the push logic contained within the
Pickup
class, enhancing readability and maintainability.Overall, your implementation looks great for a starting point, and with a few tweaks, you can enhance its functionality and performance. Good luck with your project!
Best, [Your Name]
April 28, 2025 at 10:01 pm #18061::Thanks for sharing your code Nathaniel. In the part 17 video, I recode the pickup functionality, as there were a couple of problems with it, some of which Alp has highlighted above.
The most important issue in our code (and in ours before Part 17), in my opinion, is poor separation of concerns. You will notice that the functionality to move the pickup is spread across 2 scripts:
Pickup
andPlayerCollector
. What I did in Part 17 was to letPickup.cs
handle the movement of pickup to the player entirely — allPlayerCollector
did was check whether the pickup was in range. If it was,PlayerCollector
will activate the pickup.Generally, you will want to let any script handle its own movement, instead of outsourcing it to another script. Outsourcing will lead to very long lines of code, such as in your case:
Rigidbody2D rb = col.gameObject.GetComponent<Rigidbody2D>();
It will also cause code to be buggier and harder to debug in the long run, because it becomes difficult to keep track of how many scripts are controlling a single GameObject.
The other thing I did in Part 17 was to remove the Rigidbody on the pickup and use code entirely to detect the collision. This is a significant optimisation, because it removes the pickup from the physics simulation. Since pickups can use a circular collider, we can simply have the pickup check how far away it is from the player every time it is moved, and if it is close enough, to consider itself collected, without the use of any collider.
That being said, great work on trying to customise the script on your own! I personally learnt game development through years of modding existing games, and when you diverge from a tutorial to try and create your own features, you are essentially doing a similar thing to what I used to do. So I’d say that’s a big…
Continue doing what you are doing! And when you are ready, check out Part 17 to see how you could’ve done things better.
April 29, 2025 at 5:24 am #18063::Thank you my friend,
I look forward to making more progress through the video series. I am scared about the weapon system overhaul. I briefly skimmed through your videos and it looks like a lot of work. I’ll be joining the patreon for that so I can read through the article at my own pace haha.
- 1 anonymous person
April 29, 2025 at 5:25 am #18064::You’re welcome, Nathaniel! It’s completely understandable to feel a bit overwhelmed by the weapon system overhaul—game development often involves a lot of moving parts. Just take it one step at a time, and don’t hesitate to reach out if you have questions or need clarification on any concepts as you progress through the series.
Joining the Patreon sounds like a great plan! It will definitely give you the opportunity to digest the material at your own pace and really grasp the concepts. Remember, the community is there to support you, so feel free to engage with others as you work through the content.
Good luck with your development journey, and have fun creating your game! If you need any help or guidance along the way, I’m here to assist you.
Best,
[Your Name]April 29, 2025 at 8:12 pm #18065::Thank you Nathaniel. The weapon system overhaul is going to be extremely challenging, but it also helps us create a system that will make our game infrastructure extremely scalable. It is a necessary evil, unfortunately.
Almost every game out there that you like will have to be coded like this. Otherwise, if we continue coding like we did in the earlier parts, when you scale up the amount of content that you have, you will run into a lot of organisational issues.
-
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: