Good day,
I’m trying to create a script to give powerup to an object, when certain event is trigered the script and all the components attached to the script is suposed to be copied to the main object temporarily thus giving it a powerup, I’m certain the event is being trigered correctly but the powerp is still not active which means the script is not being copied to the main object correctly.
Can anyone help me resolve this issue, any help would be much appreciated.
Below is the script(S) used
using System.Collections;
using System.Reflection;
using UnityEngine;
public class PowerUpEffectsHandler : MonoBehaviour
{
[SerializeField] private float powerUpDuration = 10f; // Duration for the power-up effect
[MonoBehaviourDropdown][SerializeField] private MonoBehaviour powerUpScript; // Serialized reference to the power-up script
private SpriteRenderer spriteRenderer;
private Collider2D powerUpCollider;
private LineRenderer lineRenderer;
private GameObject lineGameObject;
void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
powerUpCollider = GetComponent<Collider2D>();
}
void Update()
{
if (lineGameObject == null)
{
FindLineGameObject();
}
if (lineRenderer != null && powerUpCollider != null)
{
CheckLineIntersection();
}
}
private void FindLineGameObject()
{
GameObject[] lines = GameObject.FindGameObjectsWithTag("Line_drawn");
if (lines.Length > 0)
{
lineGameObject = lines[0]; // Assuming you want the first found object
lineRenderer = lineGameObject.GetComponent<LineRenderer>();
if (lineRenderer == null)
{
Debug.LogError("LineRenderer component not found on the assigned GameObject.");
}
}
else
{
Debug.LogError("No GameObject with tag 'Line_drawn' found.");
}
}
private void CheckLineIntersection()
{
int pointCount = lineRenderer.positionCount;
for (int i = 0; i < pointCount - 1; i++)
{
Vector2 start = lineRenderer.GetPosition(i);
Vector2 end = lineRenderer.GetPosition(i + 1);
if (powerUpCollider.OverlapPoint(start) || powerUpCollider.OverlapPoint(end))
{
Debug.Log("Line segment endpoint inside collider.");
DeactivateVisuals();
ActivatePowerUp();
break;
}
if (IsLineSegmentIntersectingCollider(start, end, powerUpCollider))
{
Debug.Log("Line segment intersecting collider.");
DeactivateVisuals();
ActivatePowerUp();
break;
}
}
}
private bool IsLineSegmentIntersectingCollider(Vector2 start, Vector2 end, Collider2D collider)
{
RaycastHit2D hit = Physics2D.Linecast(start, end);
if (hit.collider == collider)
{
Debug.Log("Line segment intersected with the collider.");
return true;
}
return false;
}
private void ActivatePowerUp()
{
MonoBehaviour powerUpScriptInstance = (MonoBehaviour)lineGameObject.GetComponent(powerUpScript.GetType());
if (powerUpScriptInstance == null)
{
Debug.Log("Power-up script not found, adding new script.");
// Add and copy the script and its fields from the power-up to the line object
Debug.Log($"Adding power-up script: {powerUpScript.GetType().Name}");
MonoBehaviour newScript = (MonoBehaviour)lineGameObject.AddComponent(powerUpScript.GetType());
FieldInfo[] fields = powerUpScript.GetType().GetFields();
foreach (FieldInfo field in fields)
{
field.SetValue(newScript, field.GetValue(powerUpScript));
}
powerUpScriptInstance = newScript;
Debug.Log($"Power-up script {powerUpScript.GetType().Name} added to {lineGameObject.name}");
}
Debug.Log($"Activating power-up script: {powerUpScript.GetType().Name}");
powerUpScriptInstance.enabled = true;
StartCoroutine(DeactivatePowerUpAfterDuration(powerUpScriptInstance, powerUpDuration));
}
private IEnumerator DeactivatePowerUpAfterDuration(MonoBehaviour script, float duration)
{
yield return new WaitForSeconds(duration);
script.enabled = false;
Debug.Log($"Power-up script {script.GetType().Name} deactivated after {duration} seconds.");
}
private void DeactivateVisuals()
{
Debug.Log("Deactivating visuals.");
if (spriteRenderer != null)
{
spriteRenderer.enabled = false; // Disable the sprite renderer
}
if (powerUpCollider != null)
{
powerUpCollider.enabled = false; // Disable the collider
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(MonoBehaviourDropdownAttribute))]
public class MonoBehaviourDropdownDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType == SerializedPropertyType.ObjectReference)
{
EditorGUI.BeginProperty(position, label, property);
MonoBehaviour[] monoBehaviours = GetAvailableMonoBehaviours(property);
List<string> options = monoBehaviours.Select(mb => mb.GetType().Name).ToList();
options.Insert(0, "None");
int selectedIndex = monoBehaviours.ToList().IndexOf(property.objectReferenceValue as MonoBehaviour) + 1;
selectedIndex = EditorGUI.Popup(position, label.text, selectedIndex, options.ToArray());
property.objectReferenceValue = selectedIndex > 0 ? monoBehaviours[selectedIndex - 1] : null;
EditorGUI.EndProperty();
}
else
{
EditorGUI.LabelField(position, label.text, "Use MonoBehaviourDropdown with MonoBehaviour.");
}
}
private MonoBehaviour[] GetAvailableMonoBehaviours(SerializedProperty property)
{
MonoBehaviour component = property.serializedObject.targetObject as MonoBehaviour;
if (component != null)
{
return component.GetComponents<MonoBehaviour>();
}
return new MonoBehaviour[0];
}
}
using System;
using UnityEngine;
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public class MonoBehaviourDropdownAttribute : PropertyAttribute
{
}