can interact if player has tool selected (in hand))

This commit is contained in:
j.mei7
2022-02-18 20:25:35 +01:00
parent 73669eaa3f
commit 3ff90d47c2
30 changed files with 505 additions and 78 deletions

View File

@@ -0,0 +1,46 @@
using UnityEngine;
/// <summary>
/// <c>Harvestable</c> represents the base class of all harvestable objects in the scene and inherits of "Interactable.cs"
/// </summary>
public abstract class Harvestable : Interactable
{
[Header("Harvestable Properties")]
[Tooltip("The time for how long the object needs to be harvested.")]
[Range(0.1f, 99.9f)]
[SerializeField]
float harvestDuration = 3f;
public ToolType toolType;
float harvestTime = 0f;// time for how long the player already "harvested" the object
/// <summary>
/// <c>IncreaseHarvestTime</c> increases the harvestTime by Time.deltaTime.
/// <code>harvestTime += Time.deltaTime;</code>
/// </summary>
public void IncreaseHarvestTime() => harvestTime += Time.deltaTime;
/// <summary>
/// <c>ResetHarvestTime</c><strong> resets the harvestTime to 0f.</strong>
/// </summary>
public void ResetHarvestTime() => harvestTime = 0f;
/// <summary>
/// <c>GetHarvestTime</c> gets the time for how long the player has already "harvested".
/// </summary>
/// <returns><strong>A float of the time for how long the player has already "harvested"</strong></returns>
public float GetHarvestTime() => harvestTime;
/// <summary>
/// <c>GetHarvestTimeLeft</c> gets the time for how long a player still has to "harvest".
/// </summary>
/// <returns>A float containig the result of <strong>harvestDuration - harvestTime</strong></returns>
public float GetHarvestTimeLeft() => harvestDuration - harvestTime;
/// <summary>
/// <c>GetHarvestDuration</c> gets the time for how long the object needs to be harvested until the interact method triggers.
/// </summary>
/// <returns><strong>A float of the time for how long the object needs to be harvested until the interact method triggers</strong></returns>
public float GetHarvestDuration() => harvestDuration;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05a54d359a6f37f4096b2163dcfeaaea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
using UnityEngine;
/// <summary>
/// <c>Interactable</c> represents the base class of all interactable objects in the scene
/// </summary>
public abstract class Interactable : MonoBehaviour
{
/// <summary>
/// <c>InteractinType</c> is the type of an interaction. So the "PlayerInteractin.cs" can handle the interaction input.
///
/// <list type="bullet">
/// <item>Click: A single click which triggers the Interact Method</item>
/// <item>Hold: Holding a until time is reached an then triggers the Interact Method(Time resets if the Player stops holding)</item>
/// <item>Harvest: Same as Hold but time does not reset. So the time progress gets saved. Used for class "Harvastable.cs"</item>
/// </list>
/// </summary>
public enum InteractionType {
Click,
Hold,
Harvest
}
[Header("Interactable Properties")]
public InteractionType interactionType;
[Tooltip("The time the player has to hold until the Interact method triggers.")]
[Range(0.1f, 99.9f)]
[SerializeField]
float holdDuration = 1f; // The time the player has to hold until the Interact method triggers
float holdTime; // The time for how long the player has already pressed
// Used to measure the distance between the player and the object
Transform playerTransform;
[Tooltip("The range in which the player can interact with an object")]
[Range(1f, 50f)]
[SerializeField]
float radius = 3f;
[SerializeField]
Transform centerPoint;
void Awake()
{
if(centerPoint == null)
{
centerPoint = gameObject.transform;
}
}
#region GETTER
/// <summary>
/// <c>GetDescription</c> gets the description of an interactable object.
/// <list type="bullet">
/// <item>The description is usally used to display a help text for the player (e.g. "Turn Lights On")</item>
/// </list>
/// </summary>
/// <returns><strong>A string containing the description of the interactable object</strong></returns>
public abstract string GetDescription();
/// <summary>
/// <c>GetHoldTime</c> gets the time for how long the player has already pressed.
/// </summary>
/// <returns><strong>A float of the time for how long the player has already pressed</strong></returns>
public float GetHoldTime() => holdTime;
/// <summary>
/// <c>GetHoldDuration</c> gets the time the player has to hold until the Interact method triggers.
/// </summary>
/// <returns><strong>A float of the time the player has to hold until the Interact method triggers</strong></returns>
public float GetHoldDuration() => holdDuration;
/// <summary>
/// <c>GetHoldTimeLeft</c> gets the time for how long a player still has to hold.
/// </summary>
/// <returns>A float containig the result of <strong>holdDuration - holdTime</strong></returns>
public float GetHoldTimeLeft() => holdDuration - holdTime;
/// <summary>
/// <c>GetRadius</c> gets the maximum distance of a player is allowed to have in order to interact with an object.
/// </summary>
/// <returns><strong>A float containing the interaction distance</strong></returns>
public float GetRadius() => radius;
#endregion
/// <summary>
/// <c>Interact</c> is the method which gets called when a player start the interaction with an object.
///
/// <list type="bullet">
/// <item>If the player clicks on an object</item>
/// <item>If the holdTime is greater or equals the holdDuration</item>
/// <item>If the harvestTime is greater or equals the harvestDuration</item>
/// </list>
///
/// It usually gets called in the "PlayerInteraction.cs"
/// </summary>
public abstract void Interact();
/// <summary>
/// <c>IncreaseHoldTime</c> increases the holdTime by Time.deltaTime.
/// <code>holdTime += Time.deltaTime;</code>
/// </summary>
public void IncreaseHoldTime() => holdTime += Time.deltaTime;
/// <summary>
/// <c>ResetHoldTime</c><strong> resets the holdTime to 0f.</strong>
/// </summary>
public void ResetHoldTime() => holdTime = 0f;
/// <summary>
/// <c>isInRange</c> checks if the player is in the interaction range of an interactable object.
///
/// <list type="bullet">
/// <item><strong>True</strong>: Player is in range</item>
/// <item><strong>False</strong>: Player is NOT in range</item>
/// </list>
/// </summary>
/// <returns>A bool which says if the player is in the interaction range of an interactable object</returns>
public bool isInRange()
{
playerTransform = GameObject.FindGameObjectWithTag("Player").gameObject.transform; // Maybe singleton later?
float distance = Vector2.Distance(centerPoint.position, playerTransform.position);
if(distance <= radius)
{
return true;
}
else
{
return false;
}
}
// Show interactable range in editor but NOT IN-GAME
private void OnDrawGizmosSelected()
{
// Same as in "Awake()", cause the object does not get "awakend" in inspector
if (centerPoint == null)
{
centerPoint = gameObject.transform;
}
// Gizmos are only visible in the scene view -> NOT visible IN-GAME (DEBUG Reasons)
Gizmos.color = Color.magenta;
Gizmos.DrawWireSphere(centerPoint.position, radius);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 185b418881f2566459c0cffeb5dfc0bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,105 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class PlayerInteraction : MonoBehaviour
{
[SerializeField]
TextMeshProUGUI interactionText;
[SerializeField]
Image interactionProgressImg;
void Update()
{
bool successfulHit = false;
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if(hit.collider != null)
{
Interactable interactable = hit.collider.gameObject.GetComponent<Interactable>();
if(interactable != null)
{
// Debug.Log("Target Position: " + hit.collider.gameObject.transform.position);
HandleInteraction(interactable);
successfulHit = true;
HandleInteractionText(interactable);
HandleInteractionProgress(interactable);
}
}
if (!successfulHit)
{
interactionText.text = "";
interactionProgressImg.fillAmount = 0;
}
}
void HandleInteractionProgress(Interactable interactable)
{
interactionProgressImg.fillAmount = interactable.GetHoldTime() / interactable.GetHoldDuration();
}
void HandleInteractionText(Interactable interactable)
{
interactionText.text = interactable.GetDescription();
interactionText.transform.position = new Vector3(Input.mousePosition.x + interactionText.rectTransform.sizeDelta.x / 2 + 20, Input.mousePosition.y - 5, Input.mousePosition.z);
}
/// <summary>
/// <c>HandleInteraction</c> <strong>handles the player interaction based on the Interactable.InteractionType.</strong>
/// </summary>
/// <param name="interactable"></param>
void HandleInteraction(Interactable interactable)
{
switch (interactable.interactionType)
{
case Interactable.InteractionType.Click:
if (Input.GetButtonDown("Interact") && interactable.isInRange())
{
interactable.Interact();
}
break;
case Interactable.InteractionType.Hold:
if (Input.GetButton("Interact") && interactable.isInRange())
{
interactable.IncreaseHoldTime();
if(interactable.GetHoldTime() > interactable.GetHoldDuration())
{
interactable.Interact();
interactable.ResetHoldTime();
}
}
else
{
interactable.ResetHoldTime();
}
break;
case Interactable.InteractionType.Harvest:
Harvestable harvestable = interactable.GetComponent<Harvestable>();
ToolItem toolItem = (ToolItem)GetComponent<InventoryController>().selectedItem;
bool isCorrectTool = (toolItem != null && toolItem.toolType == harvestable.toolType);
if (Input.GetButton("Interact") && interactable.isInRange() && isCorrectTool)
{
harvestable.IncreaseHarvestTime();
if (harvestable.GetHarvestTime() >= harvestable.GetHarvestDuration())
{
harvestable.Interact();
harvestable.ResetHarvestTime();
}
}
break;
default:
throw new System.Exception("Unsupported type of interactable");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c17c7c66da95ea747b93edf1da56ba16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using UnityEngine;
using UnityEngine.Rendering.Universal;
public class TestLight : Interactable
{
[Header("Test Light Properties")]
[SerializeField] Color color;
[SerializeField] Light2D globalLight;
public override string GetDescription()
{
if (isInRange())
return "Turn Light " + gameObject.name;
else
return "Light switch not in range";
}
public override void Interact()
{
globalLight.color = color;
Debug.Log("Color set to " + gameObject.name);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9cfe123230b3a464da8006f1a53a48e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using UnityEngine;
public class TreeInteraction : Harvestable
{
private void Start()
{
toolType = ToolType.AXE;
}
public override string GetDescription()
{
if (isInRange())
return "Baum muss weg";
else
return "Tree is not in range";
}
public override void Interact()
{
Debug.Log("Harvest BAUM");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c68a9987090906346b5bc7622cb96556
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: