This commit is contained in:
2026-06-04 10:42:23 +07:00
parent e7e90790c9
commit 9be2242378
4166 changed files with 53005 additions and 11401 deletions

View File

@@ -0,0 +1,36 @@
using UnityEngine;
namespace Invector.Throw
{
public class vThrowAnimatorEvent : StateMachineBehaviour
{
public enum ThrowEventType
{
EquipThrowable, EnableAiming, CancelAiming, StartLaunch, FinishLaunch
}
public ThrowEventType eventType;
[Range(0, 1f)]
public float time;
bool isTrigger;
vThrowManagerBase manager;
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
manager = animator.GetComponentInChildren<vThrowManagerBase>();
isTrigger = false;
}
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
if (stateInfo.normalizedTime >= time && !isTrigger)
{
OnTrigger();
}
}
protected virtual void OnTrigger()
{
isTrigger = true;
manager.TriggerAnimatorEvent(eventType);
}
}
}

View File

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

View File

@@ -0,0 +1,116 @@
using UnityEngine;
namespace Invector.Throw
{
[vClassHeader("THROW COLLECTABLE", false)]
public class vThrowCollectable : vMonoBehaviour
{
public string throwableName;
public int amount = 1;
public bool destroyAfter = true;
public UnityEngine.Events.UnityEvent onCanCollect;
public UnityEngine.Events.UnityEvent onCanCollectFromInventory;
public UnityEngine.Events.UnityEvent onIsStandAloneManager;
public UnityEngine.Events.UnityEvent onIsInventoryManager;
public UnityEngine.Events.UnityEvent onCollectObject;
public UnityEngine.Events.UnityEvent onReachMaxObjects;
public UnityEngine.Events.UnityEvent onEnterTrigger;
public UnityEngine.Events.UnityEvent onExitTrigger;
vThrowManagerBase throwManager;
bool isInventory => throwManager != null && throwManager is vThrowManagerInventory;
Collider _throwManagerCollider;
protected bool canCollect;
bool _isInventory;
private void OnTriggerStay(Collider other)
{
if (throwManager != null)
{
UpdateThrowInfo(false);
return;
}
if (other.gameObject.CompareTag("Player"))
throwManager = other.GetComponentInChildren<vThrowManagerBase>();
if (throwManager != null)
{
_throwManagerCollider = other;
onEnterTrigger.Invoke();
}
UpdateThrowInfo(true);
}
private void OnTriggerExit(Collider other)
{
if (_throwManagerCollider != null && other.gameObject == _throwManagerCollider.gameObject)
{
_throwManagerCollider = null;
throwManager = null;
onExitTrigger.Invoke();
}
}
public void UpdateThrowInfo(bool firstEnter)
{
if (throwManager != null)
{
if (isInventory != _isInventory || firstEnter)
{
if (isInventory)
{
onIsInventoryManager.Invoke();
}
else onIsStandAloneManager.Invoke();
_isInventory = isInventory;
}
var _canCollect = throwManager.CanCollectThrowable(throwableName, out int remainingAmount);
if (canCollect != _canCollect || firstEnter)
{
canCollect = _canCollect;
if (_canCollect)
{
if (isInventory) onCanCollectFromInventory.Invoke();
else onCanCollect.Invoke();
}
else
{
onReachMaxObjects.Invoke();
}
}
}
}
public void UpdateThrowObj()
{
if (throwManager.CanCollectThrowable(throwableName, out int remainingAmount))
{
throwManager.OnCollectThrowable(throwableName, amount);
if (amount <= remainingAmount)
{
if (destroyAfter) Destroy(this.gameObject);
}
else
{
amount -= remainingAmount;
if (amount <= 0)
{
if (destroyAfter) Destroy(this.gameObject);
}
}
onCollectObject.Invoke();
}
else
{
onReachMaxObjects.Invoke();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4c9fbd7863561794c92d957d0295c2ec
timeCreated: 1501612221
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using UnityEngine;
namespace Invector.Throw
{
[RequireComponent(typeof(LineRenderer))]
[vClassHeader("Line Controller", openClose = false)]
public class vThrowLineController : vThrowVisualControlBase
{
protected LineRenderer line;
public string materialTextureChannel = "_MainTex";
public string materialColorChannel = "_Color";
public float lineWidthMultiplier = 1f;
protected override void OnInit(vThrowManagerBase tm)
{
line = GetComponent<LineRenderer>();
}
public override void OnChangeVisual(vThrowVisualSettings settings)
{
if (settings != null && line)
{
line.enabled = settings.useLine;
SetLineColor(settings.lineRendererColor);
SetLineWidth(settings.lineRendererWidth);
SetLineTexture(settings.lineTexture);
SetLineAlignment(settings.lineAlignment);
SetLineTextureMode(settings.lineTextureMode);
SetLineTextureScale(settings.lineTile);
SetLineTextureOffset(settings.lineOffset);
}
}
public virtual void SetLineColor(Color color)
{
line.material.SetColor(materialColorChannel, color);
}
public virtual void SetLineAlignment(LineAlignment alignment)
{
line.alignment = alignment;
}
public virtual void SetLineWidth(float size)
{
line.widthMultiplier = size * lineWidthMultiplier;
}
public virtual void SetLineTexture(Texture2D texture)
{
line.material.SetTexture(materialTextureChannel, texture);
}
public virtual void SetLineTextureMode(LineTextureMode lineTextureMode)
{
line.textureMode = lineTextureMode;
}
public virtual void SetLineTextureScale(Vector2 scale)
{
line.material.SetTextureScale(materialTextureChannel, scale);
}
public virtual void SetLineTextureOffset(Vector2 offset)
{
line.material.SetTextureOffset(materialTextureChannel, offset);
}
}
}

View File

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

View File

@@ -0,0 +1,279 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Invector.Throw
{
[vClassHeader("THROW MANAGER STANDALONE")]
public class vThrowManager : vThrowManagerBase
{
[System.Serializable]
public class Throwable
{
public string name = "ThrowableName";
public Transform handler;
public vThrowableObject throwable;
public Sprite sprite;
public int amount;
public int maxAmount;
vThrowableObject _throwableInHandler;
internal vThrowableObject throwableInHandler
{
get
{
if (_throwableInHandler == null)
{
_throwableInHandler = Instantiate(throwable, handler);
_throwableInHandler.transform.localPosition = Vector3.zero;
_throwableInHandler.transform.localEulerAngles = Vector3.zero;
_throwableInHandler.gameObject.SetActive(false);
}
return _throwableInHandler;
}
}
public void ResetThrowable()
{
_throwableInHandler = null;
}
internal void SetActive(bool value)
{
if (_throwableInHandler)
{
_throwableInHandler.gameObject.SetActive(value);
}
}
}
[vEditorToolbar("Throwables")]
[SerializeField]
protected List<Throwable> throwables;
[SerializeField] protected int defaultMaxAmount = 6;
public int indexOfCurrentThrowable;
public virtual List<Throwable> Throwables { get => throwables; }
protected Throwable _currentThrowable;
protected vThrowUI _ui;
public virtual vThrowUI ui
{
get
{
if (!_ui)
{
_ui = GetComponentInChildren<vThrowUI>();
if (_ui)
{
_ui.UpdateCount(this);
}
}
return _ui;
}
}
protected override IEnumerator Start()
{
yield return base.Start();
if (ui != null)
{
ui.UpdateCount(this);
}
onThrowObject.AddListener(UpdateUI);
for (int i = 0; i < Throwables.Count; i++)
{
Throwables[i].throwableInHandler.gameObject.SetActive(false);
}
}
protected override void StartThrow()
{
base.StartThrow();
CurrentThrowable.amount--;
}
protected override void Throw()
{
base.Throw();
CurrentThrowable.ResetThrowable();
}
protected override void DisableAimMode()
{
base.DisableAimMode();
if (CurrentThrowable != null && !isThrowing) CurrentThrowable.SetActive(false);
}
protected override void EquipThrowObject()
{
base.EquipThrowObject();
if (CurrentThrowable != null) CurrentThrowable.SetActive(true);
}
protected override vThrowableObject GetInstanceOfThrowable()
{
return ObjectToThrow;
}
public override int MaxThrowObjects { get => CurrentThrowable != null ? CurrentThrowable.maxAmount : 0; }
public override Sprite CurrentThrowableSprite { get => CurrentThrowable != null ? CurrentThrowable.sprite : null; }
public override int CurrentThrowAmount { get => CurrentThrowable != null ? CurrentThrowable.amount : 0; }
public override vThrowableObject ObjectToThrow { get => CurrentThrowable != null ? CurrentThrowable.throwableInHandler : null; }
public Throwable CurrentThrowable
{
get
{
if (indexOfCurrentThrowable < throwables.Count)
{
return throwables[indexOfCurrentThrowable];
}
else
{
indexOfCurrentThrowable = 0;
}
return null;
}
}
public void NextThrowable()
{
var _index = 0;
if (indexOfCurrentThrowable + 1 < throwables.Count)
{
_index = indexOfCurrentThrowable + 1;
}
if (throwables[_index].amount > 0 || !isAiming)
{
SelectThrowable(_index);
}
else if (isAiming)
{
if (throwables.Exists(t => t.amount > 0))
{
for (int i = 0; i < throwables.Count; i++)
{
if (_index + 1 < throwables.Count)
{
_index++;
}
else
{
_index = 0;
}
if (throwables[_index].amount > 0)
{
SelectThrowable(_index);
break;
}
}
}
}
UpdateUI();
}
public void PreviousThrowable()
{
var _index = throwables.Count - 1;
if (indexOfCurrentThrowable - 1 >= 0)
{
_index = indexOfCurrentThrowable - 1;
}
if (throwables[_index].amount > 0 || !isAiming)
{
SelectThrowable(_index);
}
else if (isAiming)
{
if (throwables.Exists(t => t.amount > 0))
{
for (int i = 0; i < throwables.Count; i++)
{
if (_index - 1 >= 0)
{
_index--;
}
else
{
_index = throwables.Count - 1;
}
if (throwables[_index].amount > 0)
{
SelectThrowable(_index);
break;
}
}
}
}
UpdateUI();
}
public void SelectThrowable(int indexOfThrowable)
{
if (inEnterThrowMode || isThrowing) return;
bool wasAiming = isAiming;
DisableAimMode();
ExitThrowMode();
if (indexOfThrowable >= 0 && indexOfThrowable < throwables.Count)
{
indexOfCurrentThrowable = indexOfThrowable;
}
if (wasAiming && CurrentThrowAmount > 0)
{
EnterThrowMode();
}
UpdateUI();
}
public override bool CanCollectThrowable(string throwableName, out int remainingAmount)
{
var throwable = throwables.Find(t => t.name.Equals(throwableName));
if (throwable != null)
{
remainingAmount = throwable.maxAmount - throwable.amount;
return remainingAmount > 0;
}
remainingAmount = 0;
return false;
}
public override void OnCollectThrowable(string throwableName, int amount = 1)
{
var throwable = throwables.Find(t => t.name.Equals(throwableName));
if (throwable != null)
{
int remainingAmount = throwable.maxAmount - throwable.amount;
if (remainingAmount > 0)
{
int targetAmount = 0;
if (remainingAmount >= amount)
{
targetAmount = amount;
}
else
{
targetAmount = remainingAmount;
}
throwable.amount += targetAmount;
UpdateUI();
}
}
}
protected virtual void UpdateUI()
{
if (ui != null)
{
ui.UpdateCount(this);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3488aeb9d116a01419bf76222e7bf1d4
timeCreated: 1490915601
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,666 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Invector.Throw
{
using Invector.vCharacterController;
public abstract class vThrowManagerBase : vMonoBehaviour
{
[System.Serializable]
public class VisualEvent : UnityEngine.Events.UnityEvent<vThrowVisualSettings> { }
[System.Serializable]
public class SettingsEvent : UnityEngine.Events.UnityEvent<vThrowSettings> { }
[System.Serializable]
public class ActiveEvent : UnityEngine.Events.UnityEvent<bool> { }
#region Variables
public enum CameraStyle
{
ThirdPerson, TopDown, SideScroll
}
[vEditorToolbar("Settings")]
public CameraStyle cameraStyle;
[Tooltip("Use this to enable/disable if you can or not enter ThrowMode")]
public bool canUseThrow;
[Tooltip("Check this to use the Line that draws the Throw Trajectory")]
public bool drawTrajectory = true;
public LineRenderer lineRenderer;
[Tooltip("This is the Starting point of the Throw")]
public Transform throwStartPoint;
[Tooltip("This is the Ending point (landing) of the Throw")]
public GameObject throwEnd;
public LayerMask obstacles = 1 << 0;
public vThrowSettings defaultSettings;
public vThrowVisualSettings defaultVisualSettings;
[Tooltip("Set ignore collision to the grenade to not collide with the Player")]
public bool setIgnoreCollision;
public bool debugMode;
[vSeparator("Only for ThirdPerson Camera Style")]
[Tooltip("The Third person camera right will be applied as offset to throw start point")]
public bool useThrowStartRightOffset;
[Tooltip("Sets a Offset right for the Throw Start Point"), vHideInInspector("useThrowStartRightOffset")]
public float throwStartRightOffsetMultiplier = 1f;
[vSeparator("Controller Settings")]
[Tooltip("Force the controller to walk while aiming")]
public bool walkWhileAiming;
[Tooltip("Rotate to aim point while aiming")]
public bool rotateWhileAiming = true;
public bool rotateWhileThrowing = true;
public bool strafeWhileAiming = true;
[vEditorToolbar("Inputs")]
public GenericInput throwInput = new GenericInput("Mouse0", "RB", "RB");
public GenericInput aimThrowInput = new GenericInput("G", "LB", "LB");
public bool aimHoldingButton = true;
[vEditorToolbar("Events")]
public UnityEngine.Events.UnityEvent onEquipThrowable;
public UnityEngine.Events.UnityEvent onEnableAim;
public UnityEngine.Events.UnityEvent onCancelAim;
public UnityEngine.Events.UnityEvent onStartThrowObject;
public UnityEngine.Events.UnityEvent onThrowObject;
public UnityEngine.Events.UnityEvent onCollectObject;
public UnityEngine.Events.UnityEvent onFinishThrow;
[vEditorToolbar("Visual Effect Events")]
[vSeparator("Line")]
public ActiveEvent onSetActiveLine;
[vSeparator("Indicator")]
public ActiveEvent onSetActiveIndicator;
public SettingsEvent onChangeSettings;
public VisualEvent onChangeVisualSettings;
public virtual int MaxThrowObjects { get; }
public abstract int CurrentThrowAmount { get; }
public virtual Sprite CurrentThrowableSprite { get; }
protected virtual Collider[] selfColliders { get; set; }
/// <summary>
/// Enter Aiming ThrowMode
/// </summary>
protected virtual bool isAiming { get; set; }
/// <summary>
/// "ThrowObject" animation is playing
/// </summary>
protected virtual bool isThrowing { get; set; }
/// <summary>
/// The moment you press the throwInput
/// </summary>
protected virtual bool pressThrowInput { get; set; }
protected virtual bool wasAiming { get; set; }
protected virtual bool inEnterThrowMode { get; set; }
protected virtual Vector3 surfaceNormal { get; set; }
protected virtual Transform rightUpperArm { get; set; }
protected virtual vThirdPersonInput tpInput { get; set; }
public abstract vThrowableObject ObjectToThrow { get; }
protected virtual vThrowableObject lastThrowObject { get; set; }
#endregion
#region Settings
public virtual vThrowSettings CurrentSettings
{
get
{
var settings = ObjectToThrow && ObjectToThrow.throwSettings ? ObjectToThrow.throwSettings : defaultSettings;
if (settings != lastSettings)
{
lastSettings = settings;
onChangeSettings.Invoke(lastSettings);
}
return settings;
}
}
protected virtual vThrowSettings lastSettings { get; set; }
public virtual string cameraState => tpInput.cc.isCrouching ? CurrentSettings.cameraStateCrouching : CurrentSettings.cameraStateStanding;
public virtual bool alignToSurfaceNormal => CurrentSettings.alignToSurfaceNormal;
public virtual bool alignToViewWhenNotHit => CurrentSettings.alignToViewWhenNotHit;
public virtual bool disableEndPointWhenNotHit => CurrentSettings.disableEndPointWhenNotHit;
public virtual float alignmentSmooth => CurrentSettings.alignmentSmooth;
public virtual float metersPerSeconds => CurrentSettings.metersPerSeconds;
public virtual Vector2 minMaxTime => CurrentSettings.minMaxTime;
public virtual float maxDistance => CurrentSettings.maxDistance;
public virtual float maxVelocity => CurrentSettings.maxVelocity;
public virtual float throwMaxForce => CurrentSettings.throwMaxForce;
public virtual float throwDelayTime => CurrentSettings.throwDelayTime;
public virtual float lineStepPerTime => CurrentSettings.lineStepPerTime;
public virtual float lineMaxLength => CurrentSettings.maxLineLength;
public virtual float exitThrowModeDelay => CurrentSettings.exitThrowModeDelay;
public virtual string throwAnimation => CurrentSettings.throwAnimation;
public virtual string holdingAnimation => CurrentSettings.holdingAnimation;
public virtual string cancelAnimation => CurrentSettings.cancelAnimation;
#endregion
#region Visual
public virtual vThrowVisualSettings CurrentVisualSettings
{
get
{
var settings = ObjectToThrow && ObjectToThrow.throwVisualSettings ? ObjectToThrow.throwVisualSettings : defaultVisualSettings;
if (settings != lastSettings)
{
lastVisualSettings = settings;
onChangeVisualSettings.Invoke(lastVisualSettings);
}
return settings;
}
}
protected virtual vThrowVisualSettings lastVisualSettings { get; set; }
#endregion
protected virtual IEnumerator Start()
{
yield return new WaitForEndOfFrame();
if (lineRenderer == null) lineRenderer = GetComponentInChildren<LineRenderer>(true);
if (lineRenderer)
{
lineRenderer.useWorldSpace = false;
}
if (lineRenderer && lineRenderer.gameObject.activeInHierarchy)
{
lineRenderer.gameObject.SetActive(false);
}
if (throwEnd && throwEnd.activeSelf)
{
throwEnd.SetActive(false);
}
if (transform.root.TryGetComponent(out vDrawHideMeleeWeapons drawHide))
{
onEquipThrowable.AddListener(() => drawHide.HideWeapons(true));
}
canUseThrow = true;
tpInput = GetComponentInParent<vThirdPersonInput>();
if (tpInput)
{
selfColliders = tpInput.GetComponentsInChildren<Collider>(true);
tpInput.onUpdate -= UpdateThrowInput;
tpInput.onUpdate += UpdateThrowInput;
tpInput.onFixedUpdate -= UpdateThrowBehavior;
tpInput.onFixedUpdate += UpdateThrowBehavior;
rightUpperArm = tpInput.animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
if (cameraStyle == CameraStyle.SideScroll)
{
rotateWhileAiming = true;
}
}
if (cameraStyle != CameraStyle.ThirdPerson)
{
useThrowStartRightOffset = false;
rotateWhileAiming = true;
strafeWhileAiming = true;
}
}
public virtual void CanUseThrow(bool value)
{
canUseThrow = value;
}
protected virtual bool ThrowConditions => !(ObjectToThrow == null || CurrentThrowAmount <= 0 || !tpInput.enabled || tpInput.cc.customAction || canUseThrow == false);
protected virtual void UpdateThrowBehavior()
{
CheckThrowObjectChanges();
UpdateThrow();
MoveAndRotate();
}
protected virtual void CheckThrowObjectChanges()
{
if (ObjectToThrow != lastThrowObject)
{
lastThrowObject = ObjectToThrow;
onSetActiveLine.Invoke(CurrentVisualSettings.useLine);
onSetActiveIndicator.Invoke(CurrentVisualSettings.useIndicator);
}
}
protected virtual void UpdateThrow()
{
if (isAiming)
{
tpInput.CrouchInput();
wasAiming = true;
tpInput.SetWalkByDefault(walkWhileAiming);
if (string.IsNullOrEmpty(cameraState) == false && tpInput.customCameraState != cameraState) tpInput.ChangeCameraStateWithLerp(cameraState);
CalculateAimPoint();
if (drawTrajectory) DrawTrajectory();
if (debugMode) Debug.DrawLine(startPoint, aimPoint, Color.cyan);
}
else if (!inEnterThrowMode)
{
if (wasAiming)
{
tpInput.ResetWalkByDefault();
if (string.IsNullOrEmpty(cameraState) == false && tpInput.customCameraState == cameraState) tpInput.ResetCameraState();
if (lineRenderer && lineRenderer.gameObject.activeInHierarchy)
{
lineRenderer.gameObject.SetActive(false);
}
if (throwEnd && throwEnd.activeSelf)
{
throwEnd.SetActive(false);
}
}
wasAiming = false;
}
if (pressThrowInput)
{
isThrowing = true;
pressThrowInput = false;
tpInput.animator.SetBool("IsAiming", false);
tpInput.animator.CrossFadeInFixedTime(throwAnimation, 0.2f);
}
}
protected virtual void MoveAndRotate()
{
if (isAiming || isThrowing || inEnterThrowMode)
{
tpInput.MoveInput();
switch (cameraStyle)
{
case CameraStyle.ThirdPerson:
if (rotateWhileAiming && !isThrowing || (isThrowing && rotateWhileThrowing))
{
tpInput.cc.RotateToDirection(tpInput.cameraMain.transform.forward);
}
break;
case CameraStyle.TopDown:
var dir = aimDirection;
dir.y = 0;
if (isThrowing || rotateWhileAiming) tpInput.cc.RotateToDirection(dir);
break;
case CameraStyle.SideScroll:
///
break;
}
}
}
protected virtual void UpdateThrowInput()
{
if (!ThrowConditions)
{
return;
}
if (aimThrowInput.GetButtonDown() && !inEnterThrowMode && !isThrowing && !isAiming)
{
EnterThrowMode();
return;
}
if (aimThrowInput.GetButtonUp() && aimHoldingButton && (isAiming || inEnterThrowMode) && !isThrowing)
{
ExitThrowMode();
}
if (isAiming && !isThrowing && !pressThrowInput)
{
if (throwInput.GetButtonDown())
{
pressThrowInput = true;
}
}
if (!aimHoldingButton && aimThrowInput.GetButtonDown() && !pressThrowInput && (isAiming || inEnterThrowMode) && !isThrowing)
{
ExitThrowMode();
}
}
protected virtual vThrowableObject GetInstanceOfThrowable()
{
return Instantiate(ObjectToThrow, startPoint, Quaternion.identity);
}
protected virtual void Throw()
{
LaunchObject(GetInstanceOfThrowable());
ExitThrowMode();
}
protected virtual void LaunchObject(vThrowableObject throwable)
{
if (setIgnoreCollision)
{
var _colliders = throwable.GetComponentsInChildren<Collider>();
if (_colliders.Length > 0)
{
foreach (var _collider in _colliders)
for (int i = 0; i < selfColliders.Length; i++)
{
Physics.IgnoreCollision(_collider, selfColliders[i], true);
}
}
}
throwable.transform.position = startPoint;
throwable.isKinematic = false;
throwable.transform.parent = null;
throwable.onThrow.Invoke(tpInput.transform);
throwable.selfRigidbody.linearVelocity = StartVelocity;
onThrowObject.Invoke();
}
protected virtual void DrawTrajectory()
{
float time = Vector3.Distance(startPoint, aimPoint) * metersPerSeconds;
time = Mathf.Clamp(time, minMaxTime.x, minMaxTime.y);
Vector3? hitPoint = null;
var points = GetTrajectoryPoints(startPoint, StartVelocity, lineStepPerTime, lineMaxLength, ref hitPoint);
if (lineRenderer)
{
lineRenderer.transform.rotation = Quaternion.LookRotation(Quaternion.AngleAxis(90, transform.right) * (points[points.Count - 1] - startPoint).normalized);
if (!lineRenderer.gameObject.activeInHierarchy)
{
lineRenderer.gameObject.SetActive(true);
}
lineRenderer.positionCount = points.Count;
for (int i = 0; i < lineRenderer.positionCount; i++)
{
lineRenderer.SetPosition(i, lineRenderer.transform.InverseTransformPoint(points[i]));
}
}
if (throwEnd)
{
if (!throwEnd.activeSelf)
{
if ((!disableEndPointWhenNotHit || hitPoint != null))
throwEnd.SetActive(true);
}
else if (!(!disableEndPointWhenNotHit || hitPoint != null))
{
throwEnd.SetActive(false);
}
if (points.Count > 1)
{
throwEnd.transform.position = points[points.Count - 1];
throwEnd.transform.rotation = Quaternion.Lerp(throwEnd.transform.rotation, Quaternion.LookRotation(surfaceNormal, transform.up), alignmentSmooth * Time.deltaTime);
}
}
}
internal virtual void TriggerAnimatorEvent(vThrowAnimatorEvent.ThrowEventType eventType)
{
switch (eventType)
{
case vThrowAnimatorEvent.ThrowEventType.EquipThrowable:
onEquipThrowable.Invoke();
EquipThrowObject();
break;
case vThrowAnimatorEvent.ThrowEventType.EnableAiming:
EnableAimMode();
break;
case vThrowAnimatorEvent.ThrowEventType.CancelAiming:
DisableAimMode();
ExitThrowMode();
break;
case vThrowAnimatorEvent.ThrowEventType.StartLaunch:
DisableAimMode();
StartThrow();
break;
case vThrowAnimatorEvent.ThrowEventType.FinishLaunch:
Throw();
break;
}
}
protected virtual void EquipThrowObject()
{
onEquipThrowable.Invoke();
}
protected virtual void EnableAimMode()
{
inEnterThrowMode = false;
isAiming = true;
onEnableAim.Invoke();
}
protected virtual void DisableAimMode()
{
inEnterThrowMode = false;
isAiming = false;
onCancelAim.Invoke();
}
protected virtual void EnterThrowMode()
{
inEnterThrowMode = true;
tpInput.animator.CrossFadeInFixedTime(holdingAnimation, 0.2f);
tpInput.SetLockAllInput(true);
tpInput.SetStrafeLocomotion(strafeWhileAiming);
if (string.IsNullOrEmpty(cameraState) == false && tpInput.customCameraState != cameraState) tpInput.ChangeCameraStateWithLerp(cameraState);
tpInput.cc.isSprinting = false;
tpInput.animator.SetInteger("ActionState", 1);
if (cameraStyle == CameraStyle.SideScroll)
{
tpInput.cc.strafeSpeed.rotateWithCamera = true;
}
}
protected virtual void StartThrow()
{
onStartThrowObject.Invoke();
}
protected virtual void ExitThrowMode()
{
isThrowing = false;
tpInput.SetLockAllInput(false);
tpInput.SetStrafeLocomotion(false);
tpInput.cc.isSprinting = false;
tpInput.animator.SetInteger("ActionState", 0);
onFinishThrow.Invoke();
}
public virtual bool CanCollectThrowable(string throwableName, out int remainingAmount) { remainingAmount = 0; return false; }
public virtual void OnCollectThrowable(string throwableName, int amount = 1) { }
protected virtual Vector3 thirdPersonAimPoint
{
get
{
Vector3 endPoint = tpInput.cameraMain.transform.position + tpInput.cameraMain.transform.forward * maxDistance;
if (Physics.Linecast(tpInput.cameraMain.transform.position, endPoint, out RaycastHit hit, obstacles))
{
endPoint = hit.point;
}
return endPoint;
}
}
protected virtual Vector3 topDownAimPoint
{
get
{
var pos = vMousePositionHandler.Instance.WorldMousePosition(obstacles);
return pos;
}
}
protected virtual Vector3 sideScrollAimPoint
{
get
{
Vector3 screen = vMousePositionHandler.Instance.mousePosition;
screen.z = tpInput.cameraMain.WorldToScreenPoint(startPoint).z;
var world = tpInput.cameraMain.ScreenToWorldPoint(screen, Camera.MonoOrStereoscopicEye.Mono);
var local = transform.InverseTransformVector(world);
var localStart = transform.InverseTransformVector(startPoint);
local.x = localStart.x;
return transform.TransformVector(local);
}
}
protected virtual Vector3 startPoint
{
get
{
Vector3 startPosition = throwStartPoint.position;
var direction = aimPoint - throwStartPoint.position;
var localPoint = Vector3.zero;
localPoint.y = throwStartPoint.localPosition.y;
var localStartPoint = transform.InverseTransformPoint(startPosition);
Vector3 point = transform.TransformPoint(localPoint) + direction.normalized * localStartPoint.z;
if (useThrowStartRightOffset && tpInput && tpInput.tpCamera && tpInput.tpCamera.lerpState != null)
{
point += tpInput.tpCamera.transform.right * tpInput.tpCamera.lerpState.right * throwStartRightOffsetMultiplier * tpInput.tpCamera.switchRight;
}
var directionFromCenter = point - transform.TransformPoint(localPoint);
if (Physics.Linecast(transform.TransformPoint(localPoint), point, out RaycastHit hit, obstacles))
point = hit.point - directionFromCenter.normalized * 0.2f;
return point;
}
}
protected virtual Vector3 StartVelocity
{
get
{
return GetStartVelocity();
//if (cameraStyle != CameraStyle.SideScroll)
//{
// return GetStartVelocity();
//}
//else
//{
// var force = throwMaxForce;
// return aimDirection.normalized * force;
//}
}
}
protected virtual void CalculateAimPoint()
{
switch (cameraStyle)
{
case CameraStyle.ThirdPerson:
aimPoint = thirdPersonAimPoint;
break;
case CameraStyle.TopDown:
aimPoint = topDownAimPoint;
break;
case CameraStyle.SideScroll:
aimPoint = sideScrollAimPoint;
break;
}
}
protected virtual Vector3 GetStartVelocity(Vector3? startPoint = null)
{
var endPoint = this.aimPoint;
Vector3 distance = endPoint - (startPoint != null ? (Vector3)startPoint : this.startPoint);
Vector3 distanceXZ = distance;
// distanceXZ.y = 0;
float Sy = distance.y;
float Sxz = distanceXZ.magnitude;
float time = Mathf.Clamp(distance.magnitude / metersPerSeconds, minMaxTime.x, minMaxTime.y);
float Vxz = Sxz / time;
float Vy = Sy / time + 0.5f * Mathf.Abs(Physics.gravity.y) * time;
Vector3 result = distanceXZ.normalized;
result *= Vxz;
result.y = Vy;
return result.normalized * Mathf.Min(maxVelocity, result.magnitude);
}
protected virtual Vector3 PlotTrajectoryAtTime(Vector3 start, Vector3 startVelocity, float time)
{
return start + startVelocity * time + Physics.gravity * time * time * 0.5f;
}
protected virtual List<Vector3> GetTrajectoryPoints(Vector3 start, Vector3 startVelocity, float timestep, float maxLength, ref Vector3? hitPoint)
{
Vector3 prev = start;
List<Vector3> points = new List<Vector3>();
points.Add(prev);
surfaceNormal = alignToViewWhenNotHit ? (tpInput.cameraMain.transform.position - aimPoint).normalized : Vector3.up;
float distance = 0;
for (int i = 1; ; i++)
{
float t = timestep * i;
Vector3 pos = PlotTrajectoryAtTime(start, startVelocity, t);
RaycastHit hit;
var dir = (pos - prev).normalized;
if (Physics.Linecast(prev, pos + dir * 0.1f, out hit, obstacles))
{
points.Add(hit.point);
if (alignToSurfaceNormal) surfaceNormal = hit.normal;
hitPoint = hit.point;
if (debugMode) Debug.DrawLine(prev, hit.point, Color.red);
break;
}
else
{
if (debugMode) Debug.DrawLine(prev, pos, Color.red);
points.Add(pos);
distance += (pos - prev).magnitude;
prev = pos;
if (distance > maxLength) break;
}
}
return points;
}
public virtual Vector3 aimPoint
{
get; protected set;
}
public virtual Vector3 aimDirection
{
get
{
return aimPoint - startPoint;
}
}
}
}

View File

@@ -0,0 +1,16 @@
fileFormatVersion: 2
guid: 8241b7fda1fc27640810e55b17ca859f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- lineRenderer: {instanceID: 0}
- throwStartPoint: {instanceID: 0}
- throwEnd: {instanceID: 0}
- defaultSettings: {fileID: 11400000, guid: 8caa7855be6643747a8251ca4ca9a1c9, type: 2}
- defaultVisualSettings: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,374 @@
using System.Collections;
using UnityEngine;
namespace Invector.Throw
{
using System.Collections.Generic;
using vItemManager;
[vClassHeader("THROW MANAGER WITH INVENTORY")]
public class vThrowManagerInventory : vThrowManagerBase
{
[vEditorToolbar("Throwable")]
public bool useEquipArea;
[vHideInInspector("useEquipArea")]
public int indexOfEquipmentArea;
[vHideInInspector("useEquipArea", true)]
public vItemType itemType = vItemType.Consumable;
public Transform defaultHandler;
public Transform[] customHandlers;
protected override IEnumerator Start()
{
yield return base.Start();
itemManager = GetComponentInParent<vItemManager>();
itemManager.inventory.OnUpdateInventory += UpdateThrowableItems;
targetEquipArea = itemManager.inventory.equipAreas[indexOfEquipmentArea];
if (useEquipArea == false)
{
if (itemManager.items.Count > 0)
{
var items = itemManager.items.FindAll(item => item.originalObject != null && item.originalObject.TryGetComponent(out vThrowableObject throwableObject));
for (int i = 0; i < items.Count; i++)
{
items[i].canBeEquipped = false;
}
}
itemManager.onAddItem.AddListener((vItem item) =>
{
if (item.originalObject != null && item.originalObject.TryGetComponent(out vThrowableObject throwableObject))
{
item.canBeEquipped = false;
}
});
}
UpdateThrowableItems();
UpdateCurrentThrowableItem();
}
protected virtual vItemManager itemManager
{
get; set;
}
protected virtual vThrowUI _ui
{
get; set;
}
public virtual vThrowUI ui
{
get
{
if (!_ui)
{
_ui = GetComponentInChildren<vThrowUI>();
if (_ui)
{
_ui.UpdateCount(this);
}
}
return _ui;
}
}
protected virtual int lastItemID { get; set; }
/// <summary>
/// All throwables used to show in hand and to be launch
/// </summary>
public Dictionary<int, vThrowableObject> throwableInHandler = new Dictionary<int, vThrowableObject>();
/// <summary>
/// Used to store all items in the <see cref="vItemManager.itemListData"/> that contains a <see cref="vThrowableObject"/>.
/// </summary>
public virtual List<vItem> throwables { get; set; }
[vEditorToolbar("Debug"), SerializeField]
protected /*virtual*/ vItem _throwableItem; /*{ get; set; }*/
public virtual vItem CurrentThrowableItem
{
get
{
UpdateCurrentThrowableItem();
return _throwableItem;
}
}
public virtual Transform GetHandler(string name)
{
Transform handler = System.Array.Find(customHandlers, c => c.gameObject.name == name);
if (handler == null) handler = defaultHandler;
return handler;
}
public virtual vEquipArea targetEquipArea { get; set; }
[vEditorToolbar("Debug"), SerializeField]
protected /*virtual*/ vThrowableObject _objectToThrow;// { get; set; }
public virtual int indexOfCurrentThrowable { get; set; }
public virtual void UpdateThrowableItems()
{
if (!useEquipArea)
throwables = itemManager.itemListData.items.FindAll(i => i.type == itemType && i.originalObject != null && i.originalObject.TryGetComponent<vThrowableObject>(out vThrowableObject t));
if (useEquipArea && (targetEquipArea.currentEquippedItem != _throwableItem) && !isThrowing)
{
bool wasAiming = isAiming;
DisableAimMode();
ExitThrowMode();
UpdateCurrentThrowableItem();
if (wasAiming && CurrentThrowAmount > 0)
{
EnterThrowMode();
}
}
UpdateUI();
}
public virtual void UpdateCurrentThrowableItem()
{
if (isThrowing) return;
if (useEquipArea)
{
if (targetEquipArea.currentEquippedItem != _throwableItem)
{
_throwableItem = targetEquipArea.currentEquippedItem;
}
}
else
{
try
{
_throwableItem = throwables[indexOfCurrentThrowable];
}
catch
{
}
}
if (_throwableItem != null)
{
lastItemID = _throwableItem.id;
if (defaultHandler == null)
{
Debug.LogWarning("THROWMANAGER NEEDS A HANDLER ASSIGNED IN THE INSPECTOR", this);
return;
}
if (_throwableItem.originalObject && _throwableItem.originalObject.TryGetComponent(out vThrowableObject _throwable))
{
if (!throwableInHandler.ContainsKey(lastItemID))
{
throwableInHandler.Add(lastItemID, null);
}
if (throwableInHandler[lastItemID] == null)
{
throwableInHandler[lastItemID] = InstantiateNewThrowable(_throwable, GetHandler(_throwableItem.customHandler));
}
}
}
if (_throwableItem && throwableInHandler.ContainsKey(lastItemID))
_objectToThrow = throwableInHandler[lastItemID];
else if (useEquipArea && !inEnterThrowMode && !isThrowing)
{
_objectToThrow = null;
DisableAimMode();
ExitThrowMode();
}
}
protected virtual vThrowableObject InstantiateNewThrowable(vThrowableObject _throwable, Transform _handler)
{
var throwable = Instantiate(_throwable, _handler);
throwable.gameObject.SetActive(false);
throwable.transform.localPosition = Vector3.zero;
throwable.transform.localEulerAngles = Vector3.zero;
return throwable;
}
public virtual void NextThrowable()
{
var _index = 0;
if (indexOfCurrentThrowable + 1 < throwables.Count)
{
_index = indexOfCurrentThrowable + 1;
}
if (itemManager.GetAllAmount(throwables[_index].id) > 0 || !isAiming)
{
SelectThrowable(_index);
}
else if (isAiming)
{
if (throwables.Exists(t => itemManager.GetAllAmount(t.id) > 0))
{
for (int i = 0; i < throwables.Count; i++)
{
if (_index + 1 < throwables.Count)
{
_index++;
}
else
{
_index = 0;
}
if (itemManager.GetAllAmount(throwables[_index].id) > 0)
{
SelectThrowable(_index);
break;
}
}
}
}
UpdateUI();
}
public virtual void PreviousThrowable()
{
var _index = throwables.Count - 1;
if (indexOfCurrentThrowable - 1 >= 0)
{
_index = indexOfCurrentThrowable - 1;
}
if (itemManager.GetAllAmount(throwables[_index].id) > 0 || !isAiming)
{
SelectThrowable(_index);
}
else if (isAiming)
{
if (throwables.Exists(t => itemManager.GetAllAmount(t.id) > 0))
{
for (int i = 0; i < throwables.Count; i++)
{
if (_index - 1 >= 0)
{
_index--;
}
else
{
_index = throwables.Count - 1;
}
if (itemManager.GetAllAmount(throwables[_index].id) > 0)
{
SelectThrowable(_index);
break;
}
}
}
}
UpdateUI();
}
public virtual void SelectThrowable(int indexOfThrowable)
{
if (useEquipArea || inEnterThrowMode || isThrowing) return;
bool wasAiming = isAiming;
DisableAimMode();
ExitThrowMode();
if (indexOfThrowable >= 0 && indexOfThrowable < throwables.Count)
{
indexOfCurrentThrowable = indexOfThrowable;
}
if (wasAiming && CurrentThrowAmount > 0)
{
EnterThrowMode();
}
UpdateUI();
}
public virtual void UpdateUI()
{
if (ui != null)
{
ui.UpdateCount(this, false);
}
}
#region Overrides
public override int MaxThrowObjects { get => CurrentThrowableItem != null ? CurrentThrowableItem.maxStack : 0; }
public override Sprite CurrentThrowableSprite { get => CurrentThrowableItem != null ? CurrentThrowableItem.icon : null; }
public override int CurrentThrowAmount
{
get
{
if (CurrentThrowableItem)
{
if (useEquipArea == false)
return itemManager.GetAllAmount(CurrentThrowableItem.id);
else return CurrentThrowableItem.amount;
}
return 0;
}
}
public override vThrowableObject ObjectToThrow { get { return _objectToThrow; } }
protected override void StartThrow()
{
itemManager.LockInventoryInput(true);
base.StartThrow();
if (itemManager)
{
if (CurrentThrowableItem && throwableInHandler.ContainsKey(lastItemID) && throwableInHandler[lastItemID])
{
throwableInHandler[lastItemID] = null;
}
itemManager.DestroyItem(itemManager.GetItem(lastItemID), 1);
}
if (!useEquipArea)
UpdateUI();
}
protected override void Throw()
{
base.Throw();
itemManager.LockInventoryInput(false);
}
protected override void DisableAimMode()
{
base.DisableAimMode();
if (!isThrowing && throwableInHandler.ContainsKey(lastItemID) && throwableInHandler[lastItemID])
{
throwableInHandler[lastItemID].gameObject.SetActive(false);
}
}
protected override void EquipThrowObject()
{
if (throwableInHandler.ContainsKey(lastItemID) && throwableInHandler[lastItemID])
{
throwableInHandler[lastItemID].gameObject.SetActive(true);
}
base.EquipThrowObject();
}
protected override vThrowableObject GetInstanceOfThrowable()
{
return ObjectToThrow;
}
public override bool CanCollectThrowable(string throwableName, out int remainingAmount)
{
remainingAmount = 99999;
return true;
}
public override void OnCollectThrowable(string throwableName, int amount = 1)
{
/// Override to ignore this method to get throwables only from inventory
}
#endregion
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: eb61a71d8f68e2c4ea71e5f66c4c2db0
timeCreated: 1490915601
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using UnityEngine;
namespace Invector.Throw
{
[RequireComponent(typeof(Projector))]
[vClassHeader("Range Projector Controller", openClose = false)]
public class vThrowRangeProjectorController : vThrowVisualControlBase
{
protected Projector projector;
public string materialTextureChannel = "_MainTex";
public string materialColorChannel = "_Color";
public float projectorSizeMultiplier = 1f;
protected override void OnInit(vThrowManagerBase tm)
{
projector = GetComponent<Projector>();
if (tm)
{
tm.onSetActiveIndicator.AddListener((bool active) => projector.enabled = active);
}
}
public override void OnChangeVisual(vThrowVisualSettings settings)
{
if (settings != null && projector)
{
projector.enabled = settings.useIndicator;
SetProjectorColor(settings.indicatorColor);
SetProjectorSize(settings.indicatorRange);
SetProjectorTexture(settings.indicatorTexture);
}
}
public void SetProjectorColor(Color color)
{
projector.material.SetColor(materialColorChannel, color);
}
public void SetProjectorSize(float size)
{
if(tm.ObjectToThrow!=null)
projector.orthographicSize = size * projectorSizeMultiplier * tm.ObjectToThrow.indicatorRangeMultiplier;
}
public void SetProjectorTexture(Texture2D texture)
{
projector.material.SetTexture(materialTextureChannel, texture);
}
}
}

View File

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

View File

@@ -0,0 +1,34 @@
using UnityEngine;
namespace Invector.Throw
{
[CreateAssetMenu(menuName = "Invector/Throw/New ThrowSettings")]
public class vThrowSettings : ScriptableObject
{
[Tooltip("Align End point UP to surface normal direction")]
public bool alignToSurfaceNormal = true;
[Tooltip("End point UP always face to the view direction when don't has a surface")]
public bool alignToViewWhenNotHit = true;
public bool disableEndPointWhenNotHit = true;
[Tooltip("End point alignment smooth")]
public float alignmentSmooth = 20f;
[Min(0.001f)]
public float metersPerSeconds = 0.1f;
[vMinMax(0.0001f, 10)]
public Vector2 minMaxTime = new Vector2(0.1f, 1);
public float maxDistance = 100;
public float maxVelocity = 10;
public float throwMaxForce = 15f;
public float throwDelayTime = .25f;
[Min(0.001f)]
public float lineStepPerTime = .1f;
public float maxLineLength = 100;
public float exitThrowModeDelay = 0.5f;
public string cameraStateStanding = "ThrowStanding";
public string cameraStateCrouching = "ThrowCrouching";
public string throwAnimation = "ThrowObject";
public string holdingAnimation = "HoldingObject";
public string cancelAnimation = "CancelThrow";
}
}

View File

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

View File

@@ -0,0 +1,18 @@
using UnityEngine;
using UnityEngine.UI;
namespace Invector.Throw
{
public class vThrowUI : MonoBehaviour
{
public Text maxThrowCount;
public Text currentThrowCount;
public Image display;
internal virtual void UpdateCount(vThrowManagerBase throwManager,bool showMaxAmount = true)
{
if (currentThrowCount) currentThrowCount.text = throwManager.CurrentThrowAmount.ToString();
if (maxThrowCount) maxThrowCount.text = showMaxAmount? throwManager.MaxThrowObjects.ToString():"";
if (display) display.sprite = throwManager.CurrentThrowableSprite;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8c62d44258c35b24a90d91f36f02bcb5
timeCreated: 1501614917
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
namespace Invector.Throw
{
public abstract partial class vThrowVisualControlBase : vMonoBehaviour
{
protected vThrowManagerBase tm;
protected virtual void Awake()
{
tm = GetComponentInParent<vThrowManagerBase>();
if (tm)
{
OnInit(tm);
tm.onChangeVisualSettings.AddListener(OnChangeVisual);
}
}
protected abstract void OnInit(vThrowManagerBase manager);
public abstract void OnChangeVisual(vThrowVisualSettings settings);
}
}

View File

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

View File

@@ -0,0 +1,24 @@
using UnityEngine;
namespace Invector.Throw
{
[CreateAssetMenu(menuName = "Invector/Throw/New ThrowVisualSettings")]
public class vThrowVisualSettings : ScriptableObject
{
[vSeparator("Visual Line")]
public bool useLine;
[ColorUsage(true, true)]
public Color lineRendererColor = Color.white;
public float lineRendererWidth = 1f;
internal LineAlignment lineAlignment = LineAlignment.TransformZ;
public Texture2D lineTexture;
public LineTextureMode lineTextureMode = LineTextureMode.Stretch;
public Vector2 lineTile = Vector2.one;
public Vector2 lineOffset = Vector2.zero;
[vSeparator("Visual Indicator")]
public bool useIndicator;
[ColorUsage(true, true)]
public Color indicatorColor = Color.white;
public float indicatorRange = 1f;
public Texture2D indicatorTexture;
}
}

View File

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

View File

@@ -0,0 +1,45 @@
using UnityEngine;
namespace Invector.Throw
{
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody))]
[vClassHeader("Throwable Object", openClose = false)]
public class vThrowableObject : vMonoBehaviour
{
[System.Serializable]
public class ThrowSenderEvent : UnityEngine.Events.UnityEvent<Transform> { }
protected Rigidbody _rigidbody;
public vThrowSettings throwSettings;
public vThrowVisualSettings throwVisualSettings;
public float indicatorRangeMultiplier = 1f;
public ThrowSenderEvent onThrow;
public virtual Rigidbody selfRigidbody
{
get
{
if (_rigidbody == null)
{
if (TryGetComponent(out Rigidbody r)) _rigidbody = r;
else _rigidbody = gameObject.AddComponent<Rigidbody>();
}
return _rigidbody;
}
}
public static implicit operator Rigidbody(vThrowableObject throwable) => throwable.selfRigidbody;
public virtual bool isKinematic
{
get
{
return selfRigidbody.isKinematic;
}
set
{
selfRigidbody.isKinematic = value;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9b862849ae0308c439b127a1f3778273
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- indicatorTexture: {fileID: 2800000, guid: db48e0e5caa2999469a4f3aa249c188b, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: