Added pickable projectile; fixed some bugs
This commit is contained in:
parent
5f7d9fb5dc
commit
6ac8ba75d8
226
Assets/Resources/Prefabs/PickableProjectile.prefab
Normal file
226
Assets/Resources/Prefabs/PickableProjectile.prefab
Normal file
@ -0,0 +1,226 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &5993946430821065449
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1452460312376183192}
|
||||
- component: {fileID: -640855425046532091}
|
||||
- component: {fileID: 8375585699851212105}
|
||||
- component: {fileID: -7990430535451479416}
|
||||
m_Layer: 0
|
||||
m_Name: PickableProjectile
|
||||
m_TagString: Projectile
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1452460312376183192
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5993946430821065449}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 2, y: 2, z: 2}
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children:
|
||||
- {fileID: 8859797121973546175}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!50 &-640855425046532091
|
||||
Rigidbody2D:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5993946430821065449}
|
||||
m_BodyType: 0
|
||||
m_Simulated: 1
|
||||
m_UseFullKinematicContacts: 0
|
||||
m_UseAutoMass: 0
|
||||
m_Mass: 1
|
||||
m_LinearDamping: 0
|
||||
m_AngularDamping: 0.05
|
||||
m_GravityScale: 1
|
||||
m_Material: {fileID: 6200000, guid: 63f618adb0dc58844abe8ec1a9bd45a8, type: 2}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_Interpolate: 0
|
||||
m_SleepingMode: 1
|
||||
m_CollisionDetection: 0
|
||||
m_Constraints: 0
|
||||
--- !u!58 &8375585699851212105
|
||||
CircleCollider2D:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5993946430821065449}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_Density: 1
|
||||
m_Material: {fileID: 6200000, guid: 63f618adb0dc58844abe8ec1a9bd45a8, type: 2}
|
||||
m_IncludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_ExcludeLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
m_LayerOverridePriority: 0
|
||||
m_ForceSendLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ForceReceiveLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_ContactCaptureLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_CallbackLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_IsTrigger: 0
|
||||
m_UsedByEffector: 0
|
||||
m_CompositeOperation: 0
|
||||
m_CompositeOrder: 0
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Radius: 0.5
|
||||
--- !u!114 &-7990430535451479416
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5993946430821065449}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5bf80b3f74c7fe04e8064ebca52b7ad4, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
initialSpeed: 15
|
||||
maxLifetime: 5
|
||||
alignRotationToVelocity: 1
|
||||
knockback: 0
|
||||
hitLayers:
|
||||
serializedVersion: 2
|
||||
m_Bits: 0
|
||||
maxPierce: 0
|
||||
useGravity: 1
|
||||
gravityScale: 3
|
||||
owner: {fileID: 0}
|
||||
hitVfxPrefab: {fileID: 0}
|
||||
hitSfx: {fileID: 0}
|
||||
sfxVolume: 1
|
||||
heldLocalOffset: {x: 0.25, y: 0.1, z: 0}
|
||||
ignoreOwnerTimeOnThrow: 0.15
|
||||
attachPointChildName: HandPoint
|
||||
sleepVelocity: 0.05
|
||||
lockWhenLanded: 1
|
||||
maxBounces: 3
|
||||
minBounceSpeed: 0.8
|
||||
restitution: 0.6
|
||||
tangentDamping: 0.85
|
||||
groundUpTolerance: 0.25
|
||||
stickDelayAfterImpact: 0.03
|
||||
drawGizmos: 1
|
||||
gizmoColor: {r: 0.2, g: 0.8, b: 1, a: 0.35}
|
||||
--- !u!1 &6093063039154122651
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 8859797121973546175}
|
||||
- component: {fileID: 3362982869789392483}
|
||||
m_Layer: 0
|
||||
m_Name: Circle
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &8859797121973546175
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6093063039154122651}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1452460312376183192}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!212 &3362982869789392483
|
||||
SpriteRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 6093063039154122651}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 0
|
||||
m_RayTraceProcedural: 0
|
||||
m_RayTracingAccelStructBuildFlagsOverride: 0
|
||||
m_RayTracingAccelStructBuildFlags: 1
|
||||
m_SmallMeshCulling: 1
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_Sprite: {fileID: -2413806693520163455, guid: 7f76a84576351334b8517b4cd5666786, type: 3}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_FlipX: 0
|
||||
m_FlipY: 0
|
||||
m_DrawMode: 0
|
||||
m_Size: {x: 1, y: 1}
|
||||
m_AdaptiveModeThreshold: 0.5
|
||||
m_SpriteTileMode: 0
|
||||
m_WasSpriteAssigned: 1
|
||||
m_MaskInteraction: 0
|
||||
m_SpriteSortPoint: 0
|
||||
7
Assets/Resources/Prefabs/PickableProjectile.prefab.meta
Normal file
7
Assets/Resources/Prefabs/PickableProjectile.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fd3a37dc702ece42b51e5867473f0ff
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -2509,7 +2509,7 @@ GameObject:
|
||||
- component: {fileID: -592641019219869902}
|
||||
- component: {fileID: 8787207208699122079}
|
||||
- component: {fileID: 5723917688524288437}
|
||||
- component: {fileID: 1401621311817880213}
|
||||
- component: {fileID: 6106630833600239313}
|
||||
m_Layer: 0
|
||||
m_Name: Player
|
||||
m_TagString: Player
|
||||
@ -2639,7 +2639,7 @@ MonoBehaviour:
|
||||
jumpBuffer: 0.1
|
||||
jumpCut: 0.5
|
||||
animator: {fileID: 0}
|
||||
--- !u!114 &1401621311817880213
|
||||
--- !u!114 &6106630833600239313
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -2648,12 +2648,15 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 6550761235523395909}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 585b6e60cdd59114893f0ba218225d47, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 4e22b17be0e015040bb8efb0e96fa590, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
projectilePrefab: {fileID: 6769734275023686989, guid: 061e8ccf0e9e36f43ae0e92dadeb6b53, type: 3}
|
||||
muzzle: {fileID: 0}
|
||||
shotSpeed: 20
|
||||
projectilePrefab: {fileID: -7990430535451479416, guid: 7fd3a37dc702ece42b51e5867473f0ff, type: 3}
|
||||
spawnIfMissing: 1
|
||||
attachPoint: {fileID: 6550761233899429359}
|
||||
actionKey: 102
|
||||
throwSpeed: 20
|
||||
pickupRadius: 1.2
|
||||
--- !u!1 &6550761235546795891
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -36,7 +36,7 @@ namespace Projectiles2D
|
||||
|
||||
protected int remainingPierce;
|
||||
protected bool launched;
|
||||
protected GameObject owner;
|
||||
public GameObject owner;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
|
||||
@ -22,8 +22,8 @@ public class EnemyController : MonoBehaviour
|
||||
playerObj = GameManager.Instance.playerObj;
|
||||
if (playerObj == null)
|
||||
{
|
||||
Debug.Log("Player not found!");
|
||||
playerObj = GameObject.FindGameObjectWithTag("Player");
|
||||
Debug.Log("Player not found!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ public class PhysicsProjectile : BasicProjectile
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
|
||||
rb.AddForce(dir * finalSpeed * rb.mass, ForceMode2D.Impulse);
|
||||
rb.AddForce(finalSpeed * rb.mass * dir, ForceMode2D.Impulse);
|
||||
|
||||
transform.right = dir;
|
||||
|
||||
|
||||
246
Assets/Resources/Scripts/PickableProjectile.cs
Normal file
246
Assets/Resources/Scripts/PickableProjectile.cs
Normal file
@ -0,0 +1,246 @@
|
||||
using UnityEngine;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
public class PickableProjectile : BasicProjectile
|
||||
{
|
||||
public static PickableProjectile Instance { get; private set; }
|
||||
|
||||
public enum State { Held, Airborne, Grounded }
|
||||
public State CurrentState { get; private set; } = State.Grounded;
|
||||
|
||||
[Header("Pickup/Attach")]
|
||||
public Vector3 heldLocalOffset = new Vector3(0.25f, 0.1f, 0f);
|
||||
public float ignoreOwnerTimeOnThrow = 0.15f;
|
||||
public string attachPointChildName = "HandPoint";
|
||||
|
||||
[Header("Physics on ground")]
|
||||
public float sleepVelocity = 0.05f;
|
||||
public bool lockWhenLanded = true;
|
||||
|
||||
[Header("Bouncing")]
|
||||
[Tooltip("Максимум отскоков прежде чем лечь на землю.")]
|
||||
public int maxBounces = 3;
|
||||
|
||||
[Tooltip("Минимальная скорость для отскока.")]
|
||||
public float minBounceSpeed = 0.8f;
|
||||
|
||||
[Tooltip("Коэффициент упругости (0..1).")]
|
||||
[Range(0f, 1f)]
|
||||
public float restitution = 0.6f;
|
||||
|
||||
[Tooltip("Демпфирование вдоль поверхности (0..1), меньше — сильнее гасит скольжение.")]
|
||||
[Range(0f, 1f)]
|
||||
public float tangentDamping = 0.85f;
|
||||
|
||||
[Tooltip("Насколько «вверх» должна смотреть средняя нормаль, чтобы считать поверхность землёй (чем больше, тем мягче фильтр).")]
|
||||
[Range(0f, 1f)]
|
||||
public float groundUpTolerance = 0.25f;
|
||||
|
||||
[Tooltip("Маленькая пауза, чтобы не прилипнуть в кадр столкновения.")]
|
||||
public float stickDelayAfterImpact = 0.03f;
|
||||
|
||||
[Header("Gizmos")]
|
||||
public bool drawGizmos;
|
||||
public Color gizmoColor = new Color(0.2f, 0.8f, 1f, 0.35f);
|
||||
|
||||
private GameObject holder;
|
||||
private Transform holderAttachPoint;
|
||||
|
||||
private int bounceCounter = 0;
|
||||
private float lastImpactTime = -999f;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
|
||||
rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
|
||||
col.isTrigger = false;
|
||||
|
||||
BecomeGrounded(null);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
|
||||
public bool TryPickup(GameObject newHolder, Transform optionalAttachPoint = null)
|
||||
{
|
||||
if (CurrentState == State.Held) return true;
|
||||
|
||||
holder = newHolder;
|
||||
holderAttachPoint = optionalAttachPoint ?? FindAttachPointOn(holder);
|
||||
if (holderAttachPoint == null) holderAttachPoint = holder.transform;
|
||||
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
col.enabled = false;
|
||||
|
||||
transform.SetParent(holderAttachPoint, worldPositionStays: false);
|
||||
transform.localPosition = heldLocalOffset;
|
||||
transform.localRotation = Quaternion.identity;
|
||||
transform.localScale = Vector3.one * 2;
|
||||
|
||||
StartCoroutine(IgnoreOwnerTemporarily(holder, ignoreOwnerTimeOnThrow));
|
||||
|
||||
CurrentState = State.Held;
|
||||
launched = false;
|
||||
owner = holder;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Launch(Vector2 direction, float speed, GameObject throwOwner = null)
|
||||
{
|
||||
if (CurrentState == State.Held)
|
||||
{
|
||||
transform.SetParent(null, true);
|
||||
}
|
||||
|
||||
holder = throwOwner;
|
||||
holderAttachPoint = null;
|
||||
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
col.enabled = true;
|
||||
|
||||
launched = true;
|
||||
owner = throwOwner;
|
||||
|
||||
Vector2 dir = direction.sqrMagnitude > 0.0001f ? direction.normalized : Vector2.right;
|
||||
float finalSpeed = (speed > 0f) ? speed : initialSpeed;
|
||||
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
rb.AddForce(dir * finalSpeed * rb.mass, ForceMode2D.Impulse);
|
||||
transform.right = dir;
|
||||
|
||||
if (throwOwner != null && ignoreOwnerTimeOnThrow > 0f)
|
||||
StartCoroutine(IgnoreOwnerTemporarily(throwOwner, ignoreOwnerTimeOnThrow));
|
||||
|
||||
CurrentState = State.Airborne;
|
||||
bounceCounter = 0;
|
||||
}
|
||||
|
||||
protected override void OnCollisionEnter2D(Collision2D collision)
|
||||
{
|
||||
base.OnCollisionEnter2D(collision);
|
||||
|
||||
if (CurrentState == State.Airborne)
|
||||
{
|
||||
if (TryBounce(collision))
|
||||
{
|
||||
lastImpactTime = Time.time;
|
||||
return;
|
||||
}
|
||||
|
||||
BecomeGrounded(collision);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnImpactFinal(Collision2D collision)
|
||||
{
|
||||
if (!TryBounce(collision))
|
||||
BecomeGrounded(collision);
|
||||
}
|
||||
|
||||
protected override void OnImpactFinal(Collider2D other)
|
||||
{
|
||||
if (Time.time - lastImpactTime > stickDelayAfterImpact)
|
||||
BecomeGrounded(null);
|
||||
}
|
||||
|
||||
private bool TryBounce(Collision2D collision)
|
||||
{
|
||||
if (Time.time - lastImpactTime < stickDelayAfterImpact)
|
||||
return true;
|
||||
|
||||
var v = rb.linearVelocity;
|
||||
float speed = v.magnitude;
|
||||
if (speed < minBounceSpeed) return false;
|
||||
|
||||
Vector2 avgNormal = Vector2.up;
|
||||
if (collision.contactCount > 0)
|
||||
{
|
||||
avgNormal = Vector2.zero;
|
||||
for (int i = 0; i < collision.contactCount; i++)
|
||||
avgNormal += collision.GetContact(i).normal;
|
||||
avgNormal.Normalize();
|
||||
}
|
||||
|
||||
Vector2 reflected = Vector2.Reflect(v, avgNormal) * restitution;
|
||||
|
||||
Vector2 n = avgNormal;
|
||||
Vector2 vn = Vector2.Dot(reflected, n) * n;
|
||||
Vector2 vt = reflected - vn;
|
||||
reflected = vn + vt * tangentDamping;
|
||||
|
||||
rb.linearVelocity = reflected;
|
||||
rb.position += n * 0.005f;
|
||||
|
||||
bounceCounter++;
|
||||
|
||||
if (bounceCounter >= maxBounces)
|
||||
return false;
|
||||
|
||||
CurrentState = State.Airborne;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void BecomeGrounded(Collision2D collision)
|
||||
{
|
||||
launched = false;
|
||||
CurrentState = State.Grounded;
|
||||
|
||||
if (lockWhenLanded)
|
||||
{
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
rb.bodyType = RigidbodyType2D.Kinematic;
|
||||
}
|
||||
else
|
||||
{
|
||||
rb.bodyType = RigidbodyType2D.Dynamic;
|
||||
}
|
||||
|
||||
col.enabled = true;
|
||||
transform.SetParent(null, true);
|
||||
bounceCounter = 0;
|
||||
}
|
||||
|
||||
private Transform FindAttachPointOn(GameObject who)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(attachPointChildName)) return null;
|
||||
var t = who.transform.Find(attachPointChildName);
|
||||
return t;
|
||||
}
|
||||
|
||||
protected override void FixedUpdate()
|
||||
{
|
||||
base.FixedUpdate();
|
||||
|
||||
if (!lockWhenLanded && CurrentState == State.Airborne)
|
||||
{
|
||||
if (rb.linearVelocity.sqrMagnitude < (sleepVelocity * sleepVelocity))
|
||||
BecomeGrounded(null);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (!drawGizmos) return;
|
||||
Gizmos.color = gizmoColor;
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
Gizmos.DrawCube(new Vector3(heldLocalOffset.x, heldLocalOffset.y, 0), new Vector3(0.12f, 0.12f, 0.02f));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
2
Assets/Resources/Scripts/PickableProjectile.cs.meta
Normal file
2
Assets/Resources/Scripts/PickableProjectile.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bf80b3f74c7fe04e8064ebca52b7ad4
|
||||
78
Assets/Resources/Scripts/PlayerFireScript.cs
Normal file
78
Assets/Resources/Scripts/PlayerFireScript.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerFireScript : MonoBehaviour
|
||||
{
|
||||
[Header("Projectile (single instance)")]
|
||||
[SerializeField] public PickableProjectile projectilePrefab;
|
||||
public bool spawnIfMissing = true;
|
||||
|
||||
[Header("Throw / Pickup")]
|
||||
public Transform attachPoint;
|
||||
public KeyCode actionKey = KeyCode.F;
|
||||
public float throwSpeed = 20f;
|
||||
public float pickupRadius = 1.2f;
|
||||
|
||||
private PickableProjectile P => PickableProjectile.Instance;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
if (!attachPoint)
|
||||
{
|
||||
var hand = transform.Find("HandPoint");
|
||||
if (hand) attachPoint = hand;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (!Input.GetKeyDown(actionKey)) return;
|
||||
|
||||
var proj = P;
|
||||
|
||||
if (proj == null)
|
||||
{
|
||||
if (!spawnIfMissing || projectilePrefab == null)
|
||||
{
|
||||
Debug.Log("FireScript2D: projectile missing; set spawnIfMissing=true and assign projectilePrefab.");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 spawnPos = attachPoint ? attachPoint.position : transform.position;
|
||||
proj = Instantiate(projectilePrefab, spawnPos, Quaternion.identity);
|
||||
proj.TryPickup(gameObject, attachPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (proj.CurrentState == PickableProjectile.State.Held && proj.owner == gameObject)
|
||||
{
|
||||
float sx = transform.localScale.x;
|
||||
float facing = Mathf.Sign(sx == 0 ? 1 : sx);
|
||||
Vector2 dir = facing > 0 ? Vector2.right : Vector2.left;
|
||||
|
||||
proj.Launch(dir, throwSpeed, gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 grabFrom = attachPoint ? attachPoint.position : transform.position;
|
||||
float dist = Vector2.Distance(proj.transform.position, grabFrom);
|
||||
|
||||
if (proj.CurrentState != PickableProjectile.State.Held && dist <= pickupRadius)
|
||||
{
|
||||
proj.TryPickup(gameObject, attachPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
// Не в радиусе подбора — ничего не делаем
|
||||
// Debug.Log("FireScript2D: projectile is too far to pick up.");
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
// визуально показать радиус подбора
|
||||
Gizmos.color = new Color(0.2f, 0.8f, 1f, 0.35f);
|
||||
Vector3 center = attachPoint ? attachPoint.position : transform.position;
|
||||
Gizmos.DrawWireSphere(center, pickupRadius);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
2
Assets/Resources/Scripts/PlayerFireScript.cs.meta
Normal file
2
Assets/Resources/Scripts/PlayerFireScript.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e22b17be0e015040bb8efb0e96fa590
|
||||
Loading…
x
Reference in New Issue
Block a user