Reapply "Merge pull request '리듬게임' (#5) from CatsRhythmGame into main"
This reverts commit d7d5519fbf.
This commit is contained in:
8
Assets/Hovl Studio/HSFiles/Scripts/Editor.meta
Normal file
8
Assets/Hovl Studio/HSFiles/Scripts/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a05cbdbbac4e2da44a2bee7f73de12db
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
392
Assets/Hovl Studio/HSFiles/Scripts/Editor/ShaderChanger.cs
Normal file
392
Assets/Hovl Studio/HSFiles/Scripts/Editor/ShaderChanger.cs
Normal file
@@ -0,0 +1,392 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
namespace HovlStudio
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class RPChanger : EditorWindow
|
||||
{
|
||||
[InitializeOnLoadMethod]
|
||||
private static void LoadWindow()
|
||||
{
|
||||
string[] checkAsset = AssetDatabase.FindAssets("HSstartupCheck");
|
||||
foreach (var guid in checkAsset)
|
||||
{
|
||||
ShowWindow();
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GUIDToAssetPath(guid));
|
||||
}
|
||||
}
|
||||
|
||||
static private int pipeline;
|
||||
[MenuItem("Tools/RP changer for Hovl Studio assets")]
|
||||
|
||||
public static void ShowWindow()
|
||||
{
|
||||
RPChanger window = (RPChanger)EditorWindow.GetWindow(typeof(RPChanger));
|
||||
window.minSize = new Vector2(250, 140);
|
||||
window.maxSize = new Vector2(250, 140);
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
GUILayout.Label("Change VFX shaders to:");
|
||||
if (GUILayout.Button("URP/HDRP"))
|
||||
{
|
||||
FindShaders();
|
||||
ChangeToSG();
|
||||
}
|
||||
if (GUILayout.Button("Built-in RP"))
|
||||
{
|
||||
FindShaders();
|
||||
ChangeToBiRP();
|
||||
}
|
||||
GUILayout.Label("Don't forget to enable Depth and Opaque\ncheck-buttons in your URP asset seeting.", GUILayout.ExpandWidth(true));
|
||||
}
|
||||
|
||||
static Shader Add_CG, Blend_CG, LightGlow, Lit_CenterGlow, Blend_TwoSides, Blend_Normals, Ice, Distortion, ParallaxIce, BlendDistort, VolumeLaser, Explosion, SwordSlash, ShockWave, SoftNoise;
|
||||
static Shader Blend_CG_SG, LightGlow_SG, Lit_CenterGlow_SG, Blend_TwoSides_SG, Blend_Normals_SG, Ice_SG, Distortion_SG, ParallaxIce_SG,
|
||||
BlendDistort_SG, VolumeLaser_SG, Explosion_SG, SwordSlash_SG, ShockWave_SG, SoftNoise_SG;
|
||||
static Material[] shaderMaterials;
|
||||
|
||||
private static void FindShaders()
|
||||
{
|
||||
if (Shader.Find("Hovl/Particles/Add_CenterGlow") != null) Add_CG = Shader.Find("Hovl/Particles/Add_CenterGlow");
|
||||
if (Shader.Find("Hovl/Particles/Blend_CenterGlow") != null) Blend_CG = Shader.Find("Hovl/Particles/Blend_CenterGlow");
|
||||
if (Shader.Find("Hovl/Particles/LightGlow") != null) LightGlow = Shader.Find("Hovl/Particles/LightGlow");
|
||||
if (Shader.Find("Hovl/Particles/Lit_CenterGlow") != null) Lit_CenterGlow = Shader.Find("Hovl/Particles/Lit_CenterGlow");
|
||||
if (Shader.Find("Hovl/Particles/Blend_TwoSides") != null) Blend_TwoSides = Shader.Find("Hovl/Particles/Blend_TwoSides");
|
||||
if (Shader.Find("Hovl/Particles/Blend_Normals") != null) Blend_Normals = Shader.Find("Hovl/Particles/Blend_Normals");
|
||||
if (Shader.Find("Hovl/Particles/Ice") != null) Ice = Shader.Find("Hovl/Particles/Ice");
|
||||
if (Shader.Find("Hovl/Particles/Distortion") != null) Distortion = Shader.Find("Hovl/Particles/Distortion");
|
||||
if (Shader.Find("Hovl/Opaque/ParallaxIce") != null) ParallaxIce = Shader.Find("Hovl/Opaque/ParallaxIce");
|
||||
if (Shader.Find("Hovl/Particles/BlendDistort") != null) BlendDistort = Shader.Find("Hovl/Particles/BlendDistort");
|
||||
if (Shader.Find("Hovl/Particles/VolumeLaser") != null) VolumeLaser = Shader.Find("Hovl/Particles/VolumeLaser");
|
||||
if (Shader.Find("Hovl/Particles/Explosion") != null) Explosion = Shader.Find("Hovl/Particles/Explosion");
|
||||
if (Shader.Find("Hovl/Particles/SwordSlash") != null) SwordSlash = Shader.Find("Hovl/Particles/SwordSlash");
|
||||
if (Shader.Find("Hovl/Particles/ShockWave") != null) ShockWave = Shader.Find("Hovl/Particles/ShockWave");
|
||||
if (Shader.Find("Hovl/Particles/SoftNoise") != null) SoftNoise = Shader.Find("Hovl/Particles/SoftNoise");
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_LightGlow") != null) LightGlow_SG = Shader.Find("Shader Graphs/HS_LightGlow");
|
||||
if (Shader.Find("Shader Graphs/HS_Lit_CenterGlow") != null) Lit_CenterGlow_SG = Shader.Find("Shader Graphs/HS_Lit_CenterGlow");
|
||||
if (Shader.Find("Shader Graphs/HS_Blend_TwoSides") != null) Blend_TwoSides_SG = Shader.Find("Shader Graphs/HS_Blend_TwoSides");
|
||||
if (Shader.Find("Shader Graphs/HS_Blend_Normals") != null) Blend_Normals_SG = Shader.Find("Shader Graphs/HS_Blend_Normals");
|
||||
if (Shader.Find("Shader Graphs/HS_Ice") != null) Ice_SG = Shader.Find("Shader Graphs/HS_Ice");
|
||||
if (Shader.Find("Shader Graphs/HS_Distortion") != null) Distortion_SG = Shader.Find("Shader Graphs/HS_Distortion");
|
||||
if (Shader.Find("Shader Graphs/HS_ParallaxIce") != null) ParallaxIce_SG = Shader.Find("Shader Graphs/HS_ParallaxIce");
|
||||
if (Shader.Find("Shader Graphs/HS_Blend_CG") != null) Blend_CG_SG = Shader.Find("Shader Graphs/HS_Blend_CG");
|
||||
if (Shader.Find("Shader Graphs/HS_BlendDistort") != null) BlendDistort_SG = Shader.Find("Shader Graphs/HS_BlendDistort");
|
||||
if (Shader.Find("Shader Graphs/HS_VolumeLaser") != null) VolumeLaser_SG = Shader.Find("Shader Graphs/HS_VolumeLaser");
|
||||
if (Shader.Find("Shader Graphs/HS_Explosion") != null) Explosion_SG = Shader.Find("Shader Graphs/HS_Explosion");
|
||||
if (Shader.Find("Shader Graphs/HS_SwordSlash") != null) SwordSlash_SG = Shader.Find("Shader Graphs/HS_SwordSlash");
|
||||
if (Shader.Find("Shader Graphs/HS_ShockWave") != null) ShockWave_SG = Shader.Find("Shader Graphs/HS_ShockWave");
|
||||
if (Shader.Find("Shader Graphs/HS_SoftNoise") != null) SoftNoise_SG = Shader.Find("Shader Graphs/HS_SoftNoise");
|
||||
|
||||
string[] folderMat = AssetDatabase.FindAssets("t:Material", new[] { "Assets" });
|
||||
shaderMaterials = new Material[folderMat.Length];
|
||||
|
||||
for (int i = 0; i < folderMat.Length; i++)
|
||||
{
|
||||
var patch = AssetDatabase.GUIDToAssetPath(folderMat[i]);
|
||||
shaderMaterials[i] = (Material)AssetDatabase.LoadAssetAtPath(patch, typeof(Material));
|
||||
}
|
||||
}
|
||||
|
||||
static private void ChangeToSG()
|
||||
{
|
||||
foreach (var material in shaderMaterials)
|
||||
{
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_LightGlow") != null)
|
||||
{
|
||||
if (material.shader == LightGlow)
|
||||
{
|
||||
material.shader = LightGlow_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Lit_CenterGlow") != null)
|
||||
{
|
||||
if (material.shader == Lit_CenterGlow)
|
||||
{
|
||||
material.shader = Lit_CenterGlow_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Blend_TwoSides") != null)
|
||||
{
|
||||
if (material.shader == Blend_TwoSides)
|
||||
{
|
||||
material.shader = Blend_TwoSides_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Blend_Normals") != null)
|
||||
{
|
||||
if (material.shader == Blend_Normals)
|
||||
{
|
||||
material.shader = Blend_Normals_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Ice") != null)
|
||||
{
|
||||
if (material.shader == Ice)
|
||||
{
|
||||
material.shader = Ice_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_ParallaxIce") != null)
|
||||
{
|
||||
if (material.shader == ParallaxIce)
|
||||
{
|
||||
material.shader = ParallaxIce_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Distortion") != null)
|
||||
{
|
||||
if (material.shader == Distortion)
|
||||
{
|
||||
material.SetFloat("_ZWrite", 0);
|
||||
material.shader = Distortion_SG;
|
||||
material.SetFloat("_QueueControl", 1);
|
||||
material.SetFloat("_BUILTIN_QueueControl", 1);
|
||||
material.renderQueue = 2750;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Blend_CG") != null)
|
||||
{
|
||||
if (material.shader == Add_CG)
|
||||
{
|
||||
if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0);
|
||||
var cull = material.GetFloat("_CullMode");
|
||||
material.shader = Blend_CG_SG;
|
||||
material.SetFloat("_Cull", cull);
|
||||
material.SetFloat("_Blend", 2);
|
||||
material.SetFloat("_DstBlend", 1);
|
||||
material.SetFloat("_SrcBlend", 5);
|
||||
material.SetFloat("_BUILTIN_CullMode", cull);
|
||||
material.SetFloat("_BUILTIN_Blend", 2);
|
||||
material.SetFloat("_BUILTIN_DstBlend", 1);
|
||||
material.SetFloat("_BUILTIN_SrcBlend", 5);
|
||||
Debug.Log("Shaders changed successfully");
|
||||
}
|
||||
if (material.shader == Blend_CG)
|
||||
{
|
||||
if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0);
|
||||
material.shader = Blend_CG_SG;
|
||||
|
||||
}
|
||||
}
|
||||
else Debug.Log("First import shaders!");
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_BlendDistort") != null)
|
||||
{
|
||||
if (material.shader == BlendDistort)
|
||||
{
|
||||
if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0);
|
||||
material.shader = BlendDistort_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_VolumeLaser") != null)
|
||||
{
|
||||
if (material.shader == VolumeLaser)
|
||||
{
|
||||
material.shader = VolumeLaser_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_Explosion") != null)
|
||||
{
|
||||
if (material.shader == Explosion)
|
||||
{
|
||||
material.shader = Explosion_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_SwordSlash") != null)
|
||||
{
|
||||
if (material.shader == SwordSlash)
|
||||
{
|
||||
if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0);
|
||||
material.shader = SwordSlash_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_ShockWave") != null)
|
||||
{
|
||||
if (material.shader == ShockWave)
|
||||
{
|
||||
if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0);
|
||||
material.shader = ShockWave_SG;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Shader Graphs/HS_SoftNoise") != null)
|
||||
{
|
||||
if (material.shader == SoftNoise)
|
||||
{
|
||||
if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0);
|
||||
material.shader = SoftNoise_SG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static private void ChangeToBiRP()
|
||||
{
|
||||
foreach (var material in shaderMaterials)
|
||||
{
|
||||
if (Shader.Find("Hovl/Particles/LightGlow") != null)
|
||||
{
|
||||
if (material.shader == LightGlow_SG)
|
||||
{
|
||||
material.shader = LightGlow;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Lit_CenterGlow") != null)
|
||||
{
|
||||
if (material.shader == Lit_CenterGlow_SG)
|
||||
{
|
||||
material.shader = Lit_CenterGlow;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Blend_TwoSides") != null)
|
||||
{
|
||||
if (material.shader == Blend_TwoSides_SG)
|
||||
{
|
||||
material.shader = Blend_TwoSides;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Blend_Normals") != null)
|
||||
{
|
||||
if (material.shader == Blend_Normals_SG)
|
||||
{
|
||||
material.shader = Blend_Normals;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Ice") != null)
|
||||
{
|
||||
if (material.shader == Ice_SG)
|
||||
{
|
||||
material.shader = Ice;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Opaque/ParallaxIce") != null)
|
||||
{
|
||||
if (material.shader == ParallaxIce_SG)
|
||||
{
|
||||
material.shader = ParallaxIce;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Distortion") != null)
|
||||
{
|
||||
if (material.shader == Distortion_SG)
|
||||
{
|
||||
material.shader = Distortion;
|
||||
material.renderQueue = 2750;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Add_CenterGlow") != null)
|
||||
{
|
||||
if (material.shader == Blend_CG_SG)
|
||||
{
|
||||
if (material.HasProperty("_Blend"))
|
||||
{
|
||||
float blend = material.GetFloat("_Blend");
|
||||
if (blend == 2)
|
||||
{
|
||||
material.shader = Add_CG;
|
||||
Debug.Log("Shaders changed successfully");
|
||||
}
|
||||
}
|
||||
if (material.HasProperty("_BUILTIN_Blend"))
|
||||
{
|
||||
float blend = material.GetFloat("_BUILTIN_Blend");
|
||||
if (blend == 2)
|
||||
{
|
||||
material.shader = Add_CG;
|
||||
Debug.Log("Shaders changed successfully");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Blend_CenterGlow") != null)
|
||||
{
|
||||
if (material.shader == Blend_CG_SG)
|
||||
{
|
||||
if (material.HasProperty("_Blend"))
|
||||
{
|
||||
float blend = material.GetFloat("_Blend");
|
||||
if (blend == 0)
|
||||
{
|
||||
material.shader = Blend_CG;
|
||||
Debug.Log("Shaders changed successfully");
|
||||
}
|
||||
}
|
||||
if (material.HasProperty("_BUILTIN_Blend"))
|
||||
{
|
||||
float blend = material.GetFloat("_BUILTIN_Blend");
|
||||
if (blend == 0)
|
||||
{
|
||||
material.shader = Blend_CG;
|
||||
Debug.Log("Shaders changed successfully");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/BlendDistort") != null)
|
||||
{
|
||||
if (material.shader == BlendDistort_SG)
|
||||
{
|
||||
material.shader = BlendDistort;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/VolumeLaser") != null)
|
||||
{
|
||||
if (material.shader == VolumeLaser_SG)
|
||||
{
|
||||
material.shader = VolumeLaser;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/Explosion") != null)
|
||||
{
|
||||
if (material.shader == Explosion_SG)
|
||||
{
|
||||
material.shader = Explosion;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/SwordSlash") != null)
|
||||
{
|
||||
if (material.shader == SwordSlash_SG)
|
||||
{
|
||||
material.shader = SwordSlash;
|
||||
}
|
||||
}
|
||||
|
||||
if (Shader.Find("Hovl/Particles/ShockWave") != null)
|
||||
{
|
||||
if (material.shader == ShockWave_SG)
|
||||
{
|
||||
material.shader = ShockWave;
|
||||
}
|
||||
}
|
||||
if (Shader.Find("Hovl/Particles/SoftNoise") != null)
|
||||
{
|
||||
if (material.shader == SoftNoise_SG)
|
||||
{
|
||||
material.shader = SoftNoise;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f76f4e3a0234d194da27af11ef7f4bdf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/Editor/ShaderChanger.cs
|
||||
uploadId: 883376
|
||||
8
Assets/Hovl Studio/HSFiles/Scripts/For demo scenes.meta
Normal file
8
Assets/Hovl Studio/HSFiles/Scripts/For demo scenes.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ad4059f21de6304198b890b5cbaf58d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,103 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class HS_CameraController : MonoBehaviour
|
||||
{
|
||||
//camera holder
|
||||
public Transform Holder;
|
||||
public Vector3 cameraPos = new Vector3(0, 0, 0);
|
||||
public float currDistance = 5.0f;
|
||||
public float xRotate = 250.0f;
|
||||
public float yRotate = 120.0f;
|
||||
public float yMinLimit = -20f;
|
||||
public float yMaxLimit = 80f;
|
||||
public float prevDistance;
|
||||
private float x = 0.0f;
|
||||
private float y = 0.0f;
|
||||
|
||||
//For camera colliding
|
||||
RaycastHit hit;
|
||||
public LayerMask collidingLayers = ~0; //Target marker can only collide with scene layer
|
||||
private float distanceHit;
|
||||
|
||||
void Start()
|
||||
{
|
||||
var angles = transform.eulerAngles;
|
||||
x = angles.y;
|
||||
y = angles.x;
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (currDistance < 2)
|
||||
{
|
||||
currDistance = 2;
|
||||
}
|
||||
|
||||
// (currDistance - 2) / 3.5f - constant for far camera position
|
||||
var targetPos = Holder.position + new Vector3(0, (distanceHit - 2) / 3f + cameraPos[1], 0);
|
||||
|
||||
currDistance -= Input.GetAxis("Mouse ScrollWheel") * 2;
|
||||
if (Holder)
|
||||
{
|
||||
var pos = Input.mousePosition;
|
||||
float dpiScale = 1;
|
||||
if (Screen.dpi < 1) dpiScale = 1;
|
||||
if (Screen.dpi < 200) dpiScale = 1;
|
||||
else dpiScale = Screen.dpi / 200f;
|
||||
if (pos.x < 380 * dpiScale && Screen.height - pos.y < 250 * dpiScale) return;
|
||||
Cursor.visible = false;
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
x += (float)(Input.GetAxis("Mouse X") * xRotate * 0.02);
|
||||
y -= (float)(Input.GetAxis("Mouse Y") * yRotate * 0.02);
|
||||
y = ClampAngle(y, yMinLimit, yMaxLimit);
|
||||
var rotation = Quaternion.Euler(y, x, 0);
|
||||
var position = rotation * new Vector3(cameraPos[2], 0, -currDistance) + targetPos;
|
||||
//If camera collide with collidingLayers move it to this point.
|
||||
if (Physics.Raycast(targetPos, position - targetPos, out hit, (position - targetPos).magnitude, collidingLayers))
|
||||
{
|
||||
transform.position = hit.point;
|
||||
//Min(4) distance from ground for camera target point
|
||||
distanceHit = Mathf.Clamp(Vector3.Distance(targetPos, hit.point), 4, 600);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.position = position;
|
||||
distanceHit = currDistance;
|
||||
}
|
||||
transform.rotation = rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
Cursor.visible = true;
|
||||
Cursor.lockState = CursorLockMode.None;
|
||||
}
|
||||
|
||||
if (prevDistance != currDistance)
|
||||
{
|
||||
prevDistance = currDistance;
|
||||
var rot = Quaternion.Euler(y, x, 0);
|
||||
// (currDistance - 2) / 3.5f - constant for far camera position
|
||||
var po = rot * new Vector3(cameraPos[2], 0, -currDistance) + targetPos;
|
||||
transform.rotation = rot;
|
||||
transform.position = po;
|
||||
}
|
||||
}
|
||||
|
||||
static float ClampAngle(float angle, float min, float max)
|
||||
{
|
||||
if (angle < -360)
|
||||
{
|
||||
angle += 360;
|
||||
}
|
||||
if (angle > 360)
|
||||
{
|
||||
angle -= 360;
|
||||
}
|
||||
return Mathf.Clamp(angle, min, max);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4ca5efb641d8634a9ec2fdc65f1f7d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/For demo scenes/HS_CameraController.cs
|
||||
uploadId: 883376
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HS_CameraShaker : MonoBehaviour
|
||||
{
|
||||
public Transform cameraObject;
|
||||
public float amplitude;
|
||||
public float frequency;
|
||||
public float duration;
|
||||
public float timeRemaining;
|
||||
private Vector3 noiseOffset;
|
||||
private Vector3 noise;
|
||||
private AnimationCurve smoothCurve = new AnimationCurve(new Keyframe(0.0f, 0.0f, Mathf.Deg2Rad * 0.0f, Mathf.Deg2Rad * 720.0f), new Keyframe(0.2f, 1.0f), new Keyframe(1.0f, 0.0f));
|
||||
|
||||
void Start()
|
||||
{
|
||||
float rand = 32.0f;
|
||||
noiseOffset.x = Random.Range(0.0f, rand);
|
||||
noiseOffset.y = Random.Range(0.0f, rand);
|
||||
noiseOffset.z = Random.Range(0.0f, rand);
|
||||
}
|
||||
|
||||
public IEnumerator Shake(float amp, float freq, float dur, float wait)
|
||||
{
|
||||
yield return new WaitForSeconds(wait);
|
||||
float rand = 32.0f;
|
||||
noiseOffset.x = Random.Range(0.0f, rand);
|
||||
noiseOffset.y = Random.Range(0.0f, rand);
|
||||
noiseOffset.z = Random.Range(0.0f, rand);
|
||||
amplitude = amp;
|
||||
frequency = freq;
|
||||
duration = dur;
|
||||
timeRemaining += dur;
|
||||
if (timeRemaining > dur)
|
||||
{
|
||||
timeRemaining = dur;
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (timeRemaining <= 0)
|
||||
return;
|
||||
|
||||
float deltaTime = Time.deltaTime;
|
||||
timeRemaining -= deltaTime;
|
||||
float noiseOffsetDelta = deltaTime * frequency;
|
||||
|
||||
noiseOffset.x += noiseOffsetDelta;
|
||||
noiseOffset.y += noiseOffsetDelta;
|
||||
noiseOffset.z += noiseOffsetDelta;
|
||||
|
||||
noise.x = Mathf.PerlinNoise(noiseOffset.x, 0.0f);
|
||||
noise.y = Mathf.PerlinNoise(noiseOffset.y, 1.0f);
|
||||
noise.z = Mathf.PerlinNoise(noiseOffset.z, 2.0f);
|
||||
|
||||
noise -= Vector3.one * 0.5f;
|
||||
noise *= amplitude;
|
||||
|
||||
float agePercent = 1.0f - (timeRemaining / duration);
|
||||
noise *= smoothCurve.Evaluate(agePercent);
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (timeRemaining <= 0)
|
||||
return;
|
||||
Vector3 positionOffset = Vector3.zero;
|
||||
Vector3 rotationOffset = Vector3.zero;
|
||||
positionOffset += noise;
|
||||
rotationOffset += noise;
|
||||
cameraObject.transform.localPosition = positionOffset;
|
||||
cameraObject.transform.localEulerAngles = rotationOffset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9da73e1bfedb57418eb344344877d2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/For demo scenes/HS_CameraShaker.cs
|
||||
uploadId: 883376
|
||||
@@ -0,0 +1,355 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace Hovl
|
||||
{
|
||||
public class HS_DemoShooting : MonoBehaviour
|
||||
{
|
||||
[Header("Fire rate")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float fireRate = 0.1f;
|
||||
float fireCountdown;
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField] Transform firePoint;
|
||||
[SerializeField] Camera cam;
|
||||
[SerializeField] Animation camAnim;
|
||||
|
||||
[Header("Projectile settings")]
|
||||
[SerializeField] float maxLength = 100f;
|
||||
[SerializeField] GameObject[] prefabs;
|
||||
|
||||
[Header("Pooling")]
|
||||
[SerializeField] int maxPoolSizePerPrefab = 40;
|
||||
|
||||
[Header("Projectile switching")]
|
||||
[SerializeField] float switchDelay = 0.4f;
|
||||
|
||||
int currentPrefabIndex;
|
||||
float buttonSaver;
|
||||
|
||||
static Transform globalPoolRoot;
|
||||
|
||||
// key = prefab instance id, value = pool list
|
||||
static readonly Dictionary<int, List<GameObject>> pools = new Dictionary<int, List<GameObject>>();
|
||||
static readonly Dictionary<int, Transform> poolParents = new Dictionary<int, Transform>();
|
||||
|
||||
void Awake()
|
||||
{
|
||||
EnsureGlobalPool();
|
||||
|
||||
if (cam == null)
|
||||
cam = Camera.main;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
Counter(0);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
HandleShooting();
|
||||
HandleProjectileSwitch();
|
||||
HandleRotation();
|
||||
|
||||
if (fireCountdown > 0f)
|
||||
fireCountdown -= Time.deltaTime;
|
||||
|
||||
buttonSaver += Time.deltaTime;
|
||||
}
|
||||
|
||||
void HandleShooting()
|
||||
{
|
||||
if (IsFirePressedThisFrame())
|
||||
{
|
||||
Shoot();
|
||||
}
|
||||
|
||||
if (IsFastFireHeld() && fireCountdown <= 0f)
|
||||
{
|
||||
Shoot();
|
||||
fireCountdown = fireRate;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleProjectileSwitch()
|
||||
{
|
||||
float horizontal = GetHorizontalInput();
|
||||
|
||||
if (horizontal < 0f && buttonSaver >= switchDelay)
|
||||
{
|
||||
buttonSaver = 0f;
|
||||
Counter(-1);
|
||||
}
|
||||
else if (horizontal > 0f && buttonSaver >= switchDelay)
|
||||
{
|
||||
buttonSaver = 0f;
|
||||
Counter(1);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleRotation()
|
||||
{
|
||||
if (cam == null)
|
||||
return;
|
||||
|
||||
Vector2 pointerPosition = GetPointerScreenPosition();
|
||||
Ray ray = cam.ScreenPointToRay(pointerPosition);
|
||||
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, maxLength))
|
||||
{
|
||||
RotateToMouseDirection(hit.point);
|
||||
}
|
||||
}
|
||||
|
||||
void Shoot()
|
||||
{
|
||||
if (prefabs == null || prefabs.Length == 0)
|
||||
return;
|
||||
|
||||
if (firePoint == null)
|
||||
{
|
||||
Debug.LogWarning("HS_DemoShooting: FirePoint is not assigned.");
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject prefab = prefabs[currentPrefabIndex];
|
||||
if (prefab == null)
|
||||
return;
|
||||
|
||||
GameObject projectile = GetProjectile(prefab);
|
||||
if (projectile == null)
|
||||
return;
|
||||
|
||||
if (camAnim != null && camAnim.clip != null)
|
||||
camAnim.Play(camAnim.clip.name);
|
||||
|
||||
Transform projectileTransform = projectile.transform;
|
||||
projectileTransform.SetParent(null, false);
|
||||
projectileTransform.SetPositionAndRotation(firePoint.position, firePoint.rotation);
|
||||
|
||||
Rigidbody rb = projectile.GetComponent<Rigidbody>();
|
||||
if (rb != null)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
rb.velocity = Vector3.zero;
|
||||
#endif
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
}
|
||||
|
||||
projectile.SetActive(true);
|
||||
|
||||
IPooledProjectile pooledProjectile = projectile.GetComponent<IPooledProjectile>();
|
||||
if (pooledProjectile != null)
|
||||
pooledProjectile.OnSpawnedFromPool();
|
||||
}
|
||||
|
||||
GameObject GetProjectile(GameObject prefab)
|
||||
{
|
||||
if (prefab == null)
|
||||
return null;
|
||||
|
||||
int prefabId = prefab.GetInstanceID();
|
||||
|
||||
if (!pools.TryGetValue(prefabId, out List<GameObject> pool))
|
||||
{
|
||||
pool = new List<GameObject>();
|
||||
pools[prefabId] = pool;
|
||||
}
|
||||
|
||||
CleanupDestroyedObjects(pool);
|
||||
|
||||
for (int i = 0; i < pool.Count; i++)
|
||||
{
|
||||
GameObject pooledObject = pool[i];
|
||||
|
||||
if (pooledObject == null)
|
||||
continue;
|
||||
|
||||
if (!pooledObject.activeInHierarchy)
|
||||
return pooledObject;
|
||||
}
|
||||
|
||||
if (GetValidObjectCount(pool) >= maxPoolSizePerPrefab)
|
||||
return null;
|
||||
|
||||
GameObject newProjectile = CreateProjectile(prefab, prefabId);
|
||||
if (newProjectile != null)
|
||||
pool.Add(newProjectile);
|
||||
|
||||
return newProjectile;
|
||||
}
|
||||
|
||||
void CleanupDestroyedObjects(List<GameObject> pool)
|
||||
{
|
||||
for (int i = pool.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (pool[i] == null)
|
||||
pool.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
int GetValidObjectCount(List<GameObject> pool)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < pool.Count; i++)
|
||||
{
|
||||
if (pool[i] != null)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
GameObject CreateProjectile(GameObject prefab, int prefabId)
|
||||
{
|
||||
Transform parent = GetOrCreatePoolParent(prefab, prefabId);
|
||||
|
||||
GameObject newProjectile = Instantiate(prefab, parent);
|
||||
newProjectile.SetActive(false);
|
||||
|
||||
return newProjectile;
|
||||
}
|
||||
|
||||
Transform GetOrCreatePoolParent(GameObject prefab, int prefabId)
|
||||
{
|
||||
if (poolParents.TryGetValue(prefabId, out Transform existingParent) && existingParent != null)
|
||||
return existingParent;
|
||||
|
||||
GameObject parentObject = new GameObject(prefab.name + "_Pool");
|
||||
parentObject.transform.SetParent(globalPoolRoot);
|
||||
poolParents[prefabId] = parentObject.transform;
|
||||
|
||||
return parentObject.transform;
|
||||
}
|
||||
|
||||
static void EnsureGlobalPool()
|
||||
{
|
||||
if (globalPoolRoot != null)
|
||||
return;
|
||||
|
||||
GameObject existing = GameObject.Find("Hovl_GlobalProjectilePool");
|
||||
if (existing != null)
|
||||
{
|
||||
globalPoolRoot = existing.transform;
|
||||
DontDestroyOnLoad(existing);
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject poolObject = new GameObject("Hovl_GlobalProjectilePool");
|
||||
DontDestroyOnLoad(poolObject);
|
||||
globalPoolRoot = poolObject.transform;
|
||||
}
|
||||
|
||||
void Counter(int count)
|
||||
{
|
||||
if (prefabs == null || prefabs.Length == 0)
|
||||
return;
|
||||
|
||||
currentPrefabIndex += count;
|
||||
|
||||
if (currentPrefabIndex >= prefabs.Length)
|
||||
currentPrefabIndex = 0;
|
||||
else if (currentPrefabIndex < 0)
|
||||
currentPrefabIndex = prefabs.Length - 1;
|
||||
}
|
||||
|
||||
void RotateToMouseDirection(Vector3 destination)
|
||||
{
|
||||
Vector3 direction = destination - transform.position;
|
||||
|
||||
if (direction.sqrMagnitude <= 0.0001f)
|
||||
return;
|
||||
|
||||
transform.rotation = Quaternion.LookRotation(direction);
|
||||
}
|
||||
|
||||
bool IsFirePressedThisFrame()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.leftButton.wasPressedThisFrame)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Input.GetButtonDown("Fire1"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsFastFireHeld()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null && Mouse.current.rightButton.isPressed)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Input.GetMouseButton(1))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float GetHorizontalInput()
|
||||
{
|
||||
float horizontal = 0f;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Keyboard.current != null)
|
||||
{
|
||||
if (Keyboard.current.aKey.isPressed)
|
||||
horizontal -= 1f;
|
||||
|
||||
if (Keyboard.current.dKey.isPressed)
|
||||
horizontal += 1f;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Mathf.Approximately(horizontal, 0f))
|
||||
{
|
||||
if (Input.GetKey(KeyCode.A))
|
||||
horizontal -= 1f;
|
||||
|
||||
if (Input.GetKey(KeyCode.D))
|
||||
horizontal += 1f;
|
||||
|
||||
if (Mathf.Approximately(horizontal, 0f))
|
||||
horizontal = Input.GetAxisRaw("Horizontal");
|
||||
}
|
||||
#endif
|
||||
|
||||
return Mathf.Clamp(horizontal, -1f, 1f);
|
||||
}
|
||||
|
||||
Vector2 GetPointerScreenPosition()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
if (Mouse.current != null)
|
||||
return Mouse.current.position.ReadValue();
|
||||
#endif
|
||||
|
||||
#if ENABLE_LEGACY_INPUT_MANAGER
|
||||
return Input.mousePosition;
|
||||
#else
|
||||
return Vector2.zero;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPooledProjectile
|
||||
{
|
||||
void OnSpawnedFromPool();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0015164b45b01e24499396ed322983f5
|
||||
timeCreated: 1536001444
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/For demo scenes/HS_DemoShooting.cs
|
||||
uploadId: 883376
|
||||
@@ -0,0 +1,101 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class HS_DemoShooting2D : MonoBehaviour
|
||||
{
|
||||
public GameObject FirePoint;
|
||||
public Camera Cam;
|
||||
public float MaxLength;
|
||||
public GameObject[] Prefabs;
|
||||
|
||||
private Ray RayMouse;
|
||||
private Vector3 direction;
|
||||
private Quaternion rotation;
|
||||
|
||||
[Header("GUI")]
|
||||
private float windowDpi;
|
||||
private int Prefab;
|
||||
private GameObject Instance;
|
||||
private float hSliderValue = 0.1f;
|
||||
private float fireCountdown = 0f;
|
||||
|
||||
//Double-click protection
|
||||
private float buttonSaver = 0f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (Screen.dpi < 1) windowDpi = 1;
|
||||
if (Screen.dpi < 200) windowDpi = 1;
|
||||
else windowDpi = Screen.dpi / 200f;
|
||||
Counter(0);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
//Single shoot
|
||||
if (Input.GetButtonDown("Fire1"))
|
||||
{
|
||||
Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
|
||||
}
|
||||
|
||||
//Fast shooting
|
||||
if (Input.GetMouseButton(1) && fireCountdown <= 0f)
|
||||
{
|
||||
Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
|
||||
fireCountdown = 0;
|
||||
fireCountdown += hSliderValue;
|
||||
}
|
||||
fireCountdown -= Time.deltaTime;
|
||||
|
||||
//To change projectiles
|
||||
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
|
||||
{
|
||||
buttonSaver = 0f;
|
||||
Counter(-1);
|
||||
}
|
||||
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
|
||||
{
|
||||
buttonSaver = 0f;
|
||||
Counter(+1);
|
||||
}
|
||||
buttonSaver += Time.deltaTime;
|
||||
|
||||
//To rotate fire point
|
||||
if (Cam != null)
|
||||
{
|
||||
var mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
transform.rotation = Quaternion.LookRotation(Vector3.forward, mousePos - transform.position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("No camera");
|
||||
}
|
||||
}
|
||||
|
||||
//GUI Text
|
||||
void OnGUI()
|
||||
{
|
||||
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button to single shoot!");
|
||||
GUI.Label(new Rect(10 * windowDpi, 25 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use and hold the right mouse button for quick shooting!");
|
||||
GUI.Label(new Rect(10 * windowDpi, 45 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Fire rate:");
|
||||
hSliderValue = GUI.HorizontalSlider(new Rect(70 * windowDpi, 50 * windowDpi, 100 * windowDpi, 20 * windowDpi), hSliderValue, 0.0f, 1.0f);
|
||||
GUI.Label(new Rect(10 * windowDpi, 65 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change projectiles!");
|
||||
}
|
||||
|
||||
// To change prefabs (count - prefab number)
|
||||
void Counter(int count)
|
||||
{
|
||||
Prefab += count;
|
||||
if (Prefab > Prefabs.Length - 1)
|
||||
{
|
||||
Prefab = 0;
|
||||
}
|
||||
else if (Prefab < 0)
|
||||
{
|
||||
Prefab = Prefabs.Length - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cedae4990f69554199024f64462bd8a
|
||||
timeCreated: 1536001444
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/For demo scenes/HS_DemoShooting2D.cs
|
||||
uploadId: 883376
|
||||
@@ -0,0 +1,292 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
//This script requires you to have setup your animator with 3 parameters, "InputMagnitude", "InputX", "InputZ"
|
||||
//With a blend tree to control the inputmagnitude and allow blending between animations.
|
||||
//Also you need to shoose Firepoint, targets > 1, Aim image from canvas and 2 target markers and camera.
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class HS_TargetProjectiles : MonoBehaviour
|
||||
{
|
||||
public float velocity = 9;
|
||||
[Space]
|
||||
|
||||
public float InputX;
|
||||
public float InputZ;
|
||||
public Vector3 desiredMoveDirection;
|
||||
public bool blockRotationPlayer;
|
||||
public float desiredRotationSpeed = 0.1f;
|
||||
public Animator anim;
|
||||
public float Speed;
|
||||
public float allowPlayerRotation = 0.1f;
|
||||
public Camera cam;
|
||||
public CharacterController controller;
|
||||
public bool isGrounded;
|
||||
private float secondLayerWeight = 0;
|
||||
|
||||
[Space]
|
||||
[Header("Animation Smoothing")]
|
||||
[Range(0, 1f)]
|
||||
public float HorizontalAnimSmoothTime = 0.2f;
|
||||
[Range(0, 1f)]
|
||||
public float VerticalAnimTime = 0.2f;
|
||||
[Range(0, 1f)]
|
||||
public float StartAnimTime = 0.3f;
|
||||
[Range(0, 1f)]
|
||||
public float StopAnimTime = 0.15f;
|
||||
|
||||
private float verticalVel;
|
||||
private Vector3 moveVector;
|
||||
|
||||
[Space]
|
||||
[Header("Effects")]
|
||||
public GameObject[] Prefabs;
|
||||
public GameObject[] PrefabsCast;
|
||||
private ParticleSystem Effect;
|
||||
private int prefabNumber;
|
||||
private Transform parentObject;
|
||||
public LayerMask collidingLayer = ~0; //Target marker can only collide with scene layer
|
||||
|
||||
|
||||
[Space]
|
||||
[Header("Canvas")]
|
||||
public Image aim;
|
||||
public Vector2 uiOffset;
|
||||
public List<Transform> screenTargets = new List<Transform>();
|
||||
private Transform target;
|
||||
private bool activeTarger = false;
|
||||
public Transform FirePoint;
|
||||
public float fireRate = 0.1f;
|
||||
private float fireCountdown = 0f;
|
||||
private bool rotateState = false;
|
||||
|
||||
[Space]
|
||||
[Header("Sound effects")]
|
||||
private AudioSource soundComponent; //Play audio from Prefabs
|
||||
private AudioClip clip;
|
||||
|
||||
[Space]
|
||||
[Header("Camera Shaker script")]
|
||||
public HS_CameraShaker cameraShaker;
|
||||
|
||||
void Start()
|
||||
{
|
||||
anim = this.GetComponent<Animator>();
|
||||
cam = Camera.main;
|
||||
controller = this.GetComponent<CharacterController>();
|
||||
|
||||
//Get clip from Audiosource from projectile if exist for playing when shooting
|
||||
if (PrefabsCast[0].GetComponent<AudioSource>())
|
||||
{
|
||||
soundComponent = PrefabsCast[0].GetComponent<AudioSource>();
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
target = screenTargets[TargetIndex()];
|
||||
|
||||
if (Input.GetMouseButtonDown(2))
|
||||
{
|
||||
Counter(-1);
|
||||
}
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
{
|
||||
Counter(+1);
|
||||
}
|
||||
|
||||
|
||||
UserInterface();
|
||||
|
||||
if (Input.GetMouseButton(0) && activeTarger)
|
||||
{
|
||||
if (rotateState == false)
|
||||
{
|
||||
StartCoroutine(RotateToTarget(fireRate, target.position));
|
||||
}
|
||||
secondLayerWeight = Mathf.Lerp(secondLayerWeight, 1, Time.deltaTime * 10);
|
||||
if (fireCountdown <= 0f)
|
||||
{
|
||||
GameObject projectile = Instantiate(Prefabs[prefabNumber], FirePoint.position, FirePoint.rotation);
|
||||
projectile.GetComponent<HS_TargetProjectile>().UpdateTarget(target, (Vector3)uiOffset);
|
||||
Effect = PrefabsCast[prefabNumber].GetComponent<ParticleSystem>();
|
||||
Effect.Play();
|
||||
//Get Audiosource from Prefabs if exist
|
||||
if (PrefabsCast[prefabNumber].GetComponent<AudioSource>())
|
||||
{
|
||||
soundComponent = PrefabsCast[prefabNumber].GetComponent<AudioSource>();
|
||||
clip = soundComponent.clip;
|
||||
soundComponent.PlayOneShot(clip);
|
||||
}
|
||||
StartCoroutine(cameraShaker.Shake(0.1f, 2, 0.2f, 0));
|
||||
fireCountdown = 0;
|
||||
fireCountdown += fireRate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
secondLayerWeight = Mathf.Lerp(secondLayerWeight, 0, Time.deltaTime * 10);
|
||||
}
|
||||
fireCountdown -= Time.deltaTime;
|
||||
|
||||
//Need second layer in the Animator
|
||||
if (anim.layerCount > 1) { anim.SetLayerWeight(1, secondLayerWeight); }
|
||||
|
||||
InputMagnitude();
|
||||
|
||||
//If you don't need the character grounded then get rid of this part.
|
||||
isGrounded = controller.isGrounded;
|
||||
if (isGrounded)
|
||||
{
|
||||
verticalVel = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalVel -= 1f * Time.deltaTime;
|
||||
}
|
||||
moveVector = new Vector3(0, verticalVel, 0);
|
||||
controller.Move(moveVector);
|
||||
}
|
||||
|
||||
void Counter(int count)
|
||||
{
|
||||
prefabNumber += count;
|
||||
if (prefabNumber > Prefabs.Length - 1)
|
||||
{
|
||||
prefabNumber = 0;
|
||||
}
|
||||
else if (prefabNumber < 0)
|
||||
{
|
||||
prefabNumber = Prefabs.Length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void UserInterface()
|
||||
{
|
||||
Vector3 screenCenter = new Vector3(Screen.width / 1.4f, Screen.height / 2, 0);
|
||||
Vector3 screenPos = Camera.main.WorldToScreenPoint(target.position + (Vector3)uiOffset);
|
||||
Vector3 CornerDistance = screenPos - screenCenter;
|
||||
Vector3 absCornerDistance = new Vector3(Mathf.Abs(CornerDistance.x), Mathf.Abs(CornerDistance.y), Mathf.Abs(CornerDistance.z));
|
||||
|
||||
//This way you can find target on the full screen
|
||||
//if (screenPos.z > 0 && screenPos.x > 0 && screenPos.x < Screen.width && screenPos.y > 0 && screenPos.y < Screen.height)
|
||||
// {screenPos.x > 0 && screenPos.y > 0 && screenPos.z > 0} - disable target if enemy backside
|
||||
//Find target near center of the screen
|
||||
if (absCornerDistance.x < screenCenter.x / 3 && absCornerDistance.y < screenCenter.y / 3 && screenPos.x > 0 && screenPos.y > 0 && screenPos.z > 0 //If target is in the middle-right of the screen
|
||||
&& !Physics.Linecast(transform.position + (Vector3)uiOffset, target.position + (Vector3)uiOffset * 2, collidingLayer)) //If player can see the target
|
||||
{
|
||||
aim.transform.position = Vector3.MoveTowards(aim.transform.position, screenPos, Time.deltaTime * 3000);
|
||||
if (!activeTarger)
|
||||
activeTarger = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Another way
|
||||
//aim.GetComponent<RectTransform>().localPosition = new Vector3(0, 0, 0);
|
||||
aim.transform.position = Vector3.MoveTowards(aim.transform.position, screenCenter, Time.deltaTime * 3000);
|
||||
if (activeTarger)
|
||||
activeTarger = false;
|
||||
}
|
||||
}
|
||||
|
||||
//Rotate player to target when attack
|
||||
public IEnumerator RotateToTarget(float rotatingTime, Vector3 targetPoint)
|
||||
{
|
||||
rotateState = true;
|
||||
float delay = rotatingTime;
|
||||
var lookPos = targetPoint - transform.position;
|
||||
lookPos.y = 0;
|
||||
var rotation = Quaternion.LookRotation(lookPos);
|
||||
while (true)
|
||||
{
|
||||
if (Speed == 0) { transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * 20); }
|
||||
delay -= Time.deltaTime;
|
||||
if (delay <= 0 || transform.rotation == rotation)
|
||||
{
|
||||
rotateState = false;
|
||||
yield break;
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerMoveAndRotation()
|
||||
{
|
||||
InputX = Input.GetAxis("Horizontal");
|
||||
InputZ = Input.GetAxis("Vertical");
|
||||
|
||||
var camera = Camera.main;
|
||||
var forward = cam.transform.forward;
|
||||
var right = cam.transform.right;
|
||||
|
||||
forward.y = 0f;
|
||||
right.y = 0f;
|
||||
|
||||
forward.Normalize();
|
||||
right.Normalize();
|
||||
|
||||
//Movement vector
|
||||
desiredMoveDirection = forward * InputZ + right * InputX;
|
||||
|
||||
//Character diagonal movement faster fix
|
||||
desiredMoveDirection.Normalize();
|
||||
|
||||
if (blockRotationPlayer == false)
|
||||
{
|
||||
//You can use desiredMoveDirection if using InputMagnitude instead of Horizontal&Vertical axis
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(forward), desiredRotationSpeed);
|
||||
//Limit back speed
|
||||
if (InputZ < -0.5)
|
||||
controller.Move(desiredMoveDirection * Time.deltaTime * (velocity / 1.5f));
|
||||
//else if (InputX < -0.1 || InputX > 0.1)
|
||||
// controller.Move(desiredMoveDirection * Time.deltaTime * (velocity / 1.2f));
|
||||
else
|
||||
controller.Move(desiredMoveDirection * Time.deltaTime * velocity);
|
||||
}
|
||||
}
|
||||
|
||||
void InputMagnitude()
|
||||
{
|
||||
//Calculate Input Vectors
|
||||
InputX = Input.GetAxis("Horizontal");
|
||||
InputZ = Input.GetAxis("Vertical");
|
||||
|
||||
anim.SetFloat("InputZ", InputZ, VerticalAnimTime, Time.deltaTime * 2f);
|
||||
anim.SetFloat("InputX", InputX, HorizontalAnimSmoothTime, Time.deltaTime * 2f);
|
||||
|
||||
//Calculate the Input Magnitude
|
||||
Speed = new Vector2(InputX, InputZ).sqrMagnitude;
|
||||
|
||||
//Physically move player
|
||||
if (Speed > allowPlayerRotation)
|
||||
{
|
||||
anim.SetFloat("InputMagnitude", Speed, StartAnimTime, Time.deltaTime);
|
||||
PlayerMoveAndRotation();
|
||||
}
|
||||
else if (Speed < allowPlayerRotation)
|
||||
{
|
||||
anim.SetFloat("InputMagnitude", Speed, StopAnimTime, Time.deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
public int TargetIndex()
|
||||
{
|
||||
float[] distances = new float[screenTargets.Count];
|
||||
|
||||
for (int i = 0; i < screenTargets.Count; i++)
|
||||
{
|
||||
distances[i] = Vector2.Distance(Camera.main.WorldToScreenPoint(screenTargets[i].position), new Vector2(Screen.width / 1.4f, Screen.height / 2));
|
||||
}
|
||||
|
||||
float minDistance = Mathf.Min(distances);
|
||||
int index = 0;
|
||||
|
||||
for (int i = 0; i < distances.Length; i++)
|
||||
{
|
||||
if (minDistance == distances[i])
|
||||
index = i;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b829ec532fb45434db685458e161d024
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/For demo scenes/HS_TargetProjectiles.cs
|
||||
uploadId: 883376
|
||||
21
Assets/Hovl Studio/HSFiles/Scripts/HS_CallBackParent.cs
Normal file
21
Assets/Hovl Studio/HSFiles/Scripts/HS_CallBackParent.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HS_CallBackParent : MonoBehaviour
|
||||
{
|
||||
[SerializeField]protected Transform parentObject;
|
||||
|
||||
//Particle system must have "Stop action - Callback" enabled for normal work.
|
||||
protected virtual void OnParticleSystemStopped()
|
||||
{
|
||||
if (parentObject != null)
|
||||
{
|
||||
transform.parent = parentObject;
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localEulerAngles = Vector3.zero;
|
||||
}
|
||||
else
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
18
Assets/Hovl Studio/HSFiles/Scripts/HS_CallBackParent.cs.meta
Normal file
18
Assets/Hovl Studio/HSFiles/Scripts/HS_CallBackParent.cs.meta
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15f64663d9bea784b8060d7fbcdc2b23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/HS_CallBackParent.cs
|
||||
uploadId: 883376
|
||||
@@ -0,0 +1,258 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class HS_ParticleCollisionInstance : MonoBehaviour
|
||||
{
|
||||
public GameObject[] EffectsOnCollision;
|
||||
public float DestroyTimeDelay =5f;
|
||||
public bool UseWorldSpacePosition;
|
||||
public float Offset =0f;
|
||||
public Vector3 rotationOffset = new Vector3(0,0,0);
|
||||
public bool useOnlyRotationOffset = true;
|
||||
public bool UseFirePointRotation;
|
||||
public bool DestoyMainEffect = false;
|
||||
|
||||
[Tooltip("Enable pooling to avoid Instantiate/Destroy spikes")]
|
||||
public bool UsePooling = true;
|
||||
|
||||
[Tooltip("Maximum number of spawned effects processed per particle collision event (per OnParticleCollision call)")]
|
||||
public int MaxSpawnsPerCollisionCall =50;
|
||||
|
||||
private ParticleSystem part;
|
||||
private List<ParticleCollisionEvent> collisionEvents = new List<ParticleCollisionEvent>();
|
||||
|
||||
// Pooling
|
||||
private static Transform poolRoot;
|
||||
private Dictionary<GameObject, Queue<GameObject>> pools = new Dictionary<GameObject, Queue<GameObject>>();
|
||||
|
||||
// Track instances that were spawned by this emitter and not yet returned to pool
|
||||
private HashSet<GameObject> activeInstances = new HashSet<GameObject>();
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
if (DestroyTimeDelay <0f) DestroyTimeDelay =0f;
|
||||
if (MaxSpawnsPerCollisionCall <1) MaxSpawnsPerCollisionCall =1;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
part = GetComponent<ParticleSystem>();
|
||||
if (poolRoot == null)
|
||||
{
|
||||
var rootGO = GameObject.Find("[PS_Effect_Pool]");
|
||||
if (rootGO == null)
|
||||
{
|
||||
rootGO = new GameObject("[PS_Effect_Pool]");
|
||||
DontDestroyOnLoad(rootGO);
|
||||
}
|
||||
poolRoot = rootGO.transform;
|
||||
}
|
||||
}
|
||||
|
||||
void OnParticleCollision(GameObject other)
|
||||
{
|
||||
if (part == null)
|
||||
part = GetComponent<ParticleSystem>();
|
||||
if (part == null)
|
||||
return; // nothing to do without particle system
|
||||
|
||||
if (EffectsOnCollision == null || EffectsOnCollision.Length ==0)
|
||||
return;
|
||||
|
||||
int numCollisionEvents = part.GetCollisionEvents(other, collisionEvents);
|
||||
int spawned =0;
|
||||
|
||||
for (int i =0; i < numCollisionEvents; i++)
|
||||
{
|
||||
if (spawned >= MaxSpawnsPerCollisionCall)
|
||||
break; // throttle
|
||||
|
||||
var hitPos = collisionEvents[i].intersection + collisionEvents[i].normal * Offset;
|
||||
|
||||
foreach (var effect in EffectsOnCollision)
|
||||
{
|
||||
if (effect == null)
|
||||
continue;
|
||||
|
||||
if (spawned >= MaxSpawnsPerCollisionCall)
|
||||
break;
|
||||
|
||||
GameObject instance = null;
|
||||
if (UsePooling)
|
||||
instance = GetPooledInstance(effect);
|
||||
else
|
||||
instance = Instantiate(effect, hitPos, Quaternion.identity) as GameObject;
|
||||
|
||||
if (instance == null)
|
||||
continue;
|
||||
|
||||
// Track as active so we can clean up if this emitter is destroyed
|
||||
activeInstances.Add(instance);
|
||||
|
||||
// Position & rotation logic
|
||||
if (UseWorldSpacePosition)
|
||||
{
|
||||
instance.transform.position = hitPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep world position consistent but do not parent to emitter to avoid accidental destruction.
|
||||
// Compute local position relative to emitter and set world position accordingly.
|
||||
var localPos = transform.InverseTransformPoint(hitPos);
|
||||
instance.transform.position = transform.TransformPoint(localPos);
|
||||
}
|
||||
|
||||
if (UseFirePointRotation)
|
||||
{
|
||||
instance.transform.LookAt(transform.position);
|
||||
}
|
||||
else if (rotationOffset != Vector3.zero && useOnlyRotationOffset)
|
||||
{
|
||||
instance.transform.rotation = Quaternion.Euler(rotationOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
instance.transform.LookAt(collisionEvents[i].intersection + collisionEvents[i].normal);
|
||||
instance.transform.rotation *= Quaternion.Euler(rotationOffset);
|
||||
}
|
||||
|
||||
// Activate and play particle systems inside the effect
|
||||
instance.SetActive(true);
|
||||
PlayParticleSystemsRecursive(instance.transform);
|
||||
|
||||
// Return to pool after a delay (or destroy if pooling disabled)
|
||||
if (UsePooling)
|
||||
StartCoroutine(ReturnToPoolAfterDelay(effect, instance, DestroyTimeDelay));
|
||||
else
|
||||
Destroy(instance, DestroyTimeDelay);
|
||||
|
||||
spawned++;
|
||||
}
|
||||
}
|
||||
|
||||
if (DestoyMainEffect == true)
|
||||
{
|
||||
Destroy(gameObject, DestroyTimeDelay +0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// Play all particle systems in the spawned effect (in case of pooled ones they might be stopped)
|
||||
private void PlayParticleSystemsRecursive(Transform root)
|
||||
{
|
||||
var systems = root.GetComponentsInChildren<ParticleSystem>(true);
|
||||
foreach (var s in systems)
|
||||
{
|
||||
// Restart the system
|
||||
try
|
||||
{
|
||||
s.Clear();
|
||||
s.Play();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Pool helpers
|
||||
private GameObject GetPooledInstance(GameObject prefab)
|
||||
{
|
||||
if (prefab == null)
|
||||
return null;
|
||||
|
||||
Queue<GameObject> q;
|
||||
if (!pools.TryGetValue(prefab, out q) || q == null)
|
||||
{
|
||||
q = new Queue<GameObject>();
|
||||
pools[prefab] = q;
|
||||
}
|
||||
|
||||
GameObject go = null;
|
||||
while (q.Count >0)
|
||||
{
|
||||
var candidate = q.Dequeue();
|
||||
if (candidate != null)
|
||||
{
|
||||
go = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (go == null)
|
||||
{
|
||||
go = Instantiate(prefab, poolRoot);
|
||||
}
|
||||
|
||||
// ensure under pool root so it survives emitter destruction
|
||||
go.transform.SetParent(poolRoot, true);
|
||||
return go;
|
||||
}
|
||||
|
||||
private IEnumerator ReturnToPoolAfterDelay(GameObject prefab, GameObject instance, float delay)
|
||||
{
|
||||
if (instance == null)
|
||||
yield break;
|
||||
|
||||
// clamp delay
|
||||
if (delay <0f) delay =0f;
|
||||
yield return new WaitForSeconds(delay);
|
||||
|
||||
if (instance == null)
|
||||
yield break;
|
||||
|
||||
// stop particle systems
|
||||
var systems = instance.GetComponentsInChildren<ParticleSystem>(true);
|
||||
foreach (var s in systems)
|
||||
{
|
||||
try { s.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); } catch { }
|
||||
}
|
||||
|
||||
// deactivate and return to pool
|
||||
instance.SetActive(false);
|
||||
|
||||
// Remove from active tracking for this emitter
|
||||
if (activeInstances.Contains(instance))
|
||||
activeInstances.Remove(instance);
|
||||
|
||||
if (prefab == null)
|
||||
{
|
||||
Destroy(instance);
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (!pools.TryGetValue(prefab, out var q) || q == null)
|
||||
pools[prefab] = new Queue<GameObject>();
|
||||
|
||||
pools[prefab].Enqueue(instance);
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
// Destroy all active instances that were spawned by this emitter
|
||||
if (activeInstances != null)
|
||||
{
|
||||
foreach (var inst in activeInstances)
|
||||
{
|
||||
if (inst != null)
|
||||
Destroy(inst);
|
||||
}
|
||||
activeInstances.Clear();
|
||||
}
|
||||
|
||||
// Destroy all pooled objects created by this emitter
|
||||
if (pools != null)
|
||||
{
|
||||
foreach (var kv in pools)
|
||||
{
|
||||
var q = kv.Value;
|
||||
if (q == null) continue;
|
||||
while (q.Count >0)
|
||||
{
|
||||
var go = q.Dequeue();
|
||||
if (go != null)
|
||||
Destroy(go);
|
||||
}
|
||||
}
|
||||
pools.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a959a1b0b8414d4fb8a68bdc12d69ed
|
||||
timeCreated: 1516192333
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/HS_ParticleCollisionInstance.cs
|
||||
uploadId: 883376
|
||||
321
Assets/Hovl Studio/HSFiles/Scripts/HS_ProjectileMover.cs
Normal file
321
Assets/Hovl Studio/HSFiles/Scripts/HS_ProjectileMover.cs
Normal file
@@ -0,0 +1,321 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Hovl
|
||||
{
|
||||
public class HS_ProjectileMover : MonoBehaviour
|
||||
{
|
||||
[SerializeField] protected float speed = 15f;
|
||||
[SerializeField] protected float hitOffset = 0f;
|
||||
[SerializeField] protected bool UseFirePointRotation;
|
||||
[SerializeField] protected Vector3 rotationOffset = Vector3.zero;
|
||||
|
||||
[Header("Effects")]
|
||||
[SerializeField] protected GameObject hit;
|
||||
[SerializeField] protected ParticleSystem hitPS;
|
||||
[SerializeField] protected GameObject flash;
|
||||
[SerializeField] protected ParticleSystem projectilePS;
|
||||
[SerializeField] protected GameObject[] Detached;
|
||||
|
||||
[Header("Components")]
|
||||
[SerializeField] protected Rigidbody rb;
|
||||
[SerializeField] protected Collider col;
|
||||
[SerializeField] protected Light lightSourse;
|
||||
|
||||
[Header("Lifetime")]
|
||||
[SerializeField] protected bool notDestroy = false;
|
||||
[SerializeField] protected float lifeTime = 5f;
|
||||
[SerializeField] protected float detachedLifeTime = 1f;
|
||||
|
||||
protected bool initialized;
|
||||
protected bool collided;
|
||||
protected Coroutine lifeRoutine;
|
||||
protected Coroutine disableAfterHitRoutine;
|
||||
|
||||
[System.Serializable]
|
||||
protected class DetachedState
|
||||
{
|
||||
public GameObject obj;
|
||||
public Transform originalParent;
|
||||
public Vector3 localPosition;
|
||||
public Quaternion localRotation;
|
||||
public Vector3 localScale;
|
||||
}
|
||||
|
||||
protected DetachedState[] detachedStates;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (rb == null)
|
||||
rb = GetComponent<Rigidbody>();
|
||||
|
||||
if (col == null)
|
||||
col = GetComponent<Collider>();
|
||||
|
||||
SetupDetachedCache();
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
initialized = true;
|
||||
|
||||
if (flash != null)
|
||||
flash.transform.SetParent(null, true);
|
||||
|
||||
StartLifeTimer();
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
collided = false;
|
||||
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
StopRunningCoroutines();
|
||||
|
||||
if (lightSourse != null)
|
||||
lightSourse.enabled = true;
|
||||
|
||||
if (col != null)
|
||||
col.enabled = true;
|
||||
|
||||
if (rb != null)
|
||||
{
|
||||
rb.constraints = RigidbodyConstraints.None;
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
rb.velocity = Vector3.zero;
|
||||
#endif
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
}
|
||||
|
||||
if (projectilePS != null)
|
||||
{
|
||||
projectilePS.Clear(true);
|
||||
projectilePS.Play(true);
|
||||
}
|
||||
|
||||
if (notDestroy)
|
||||
RestoreDetachedObjects();
|
||||
|
||||
StartLifeTimer();
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
StopRunningCoroutines();
|
||||
}
|
||||
|
||||
protected virtual void StopRunningCoroutines()
|
||||
{
|
||||
if (lifeRoutine != null)
|
||||
{
|
||||
StopCoroutine(lifeRoutine);
|
||||
lifeRoutine = null;
|
||||
}
|
||||
|
||||
if (disableAfterHitRoutine != null)
|
||||
{
|
||||
StopCoroutine(disableAfterHitRoutine);
|
||||
disableAfterHitRoutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetupDetachedCache()
|
||||
{
|
||||
if (Detached == null || Detached.Length == 0)
|
||||
return;
|
||||
|
||||
detachedStates = new DetachedState[Detached.Length];
|
||||
|
||||
for (int i = 0; i < Detached.Length; i++)
|
||||
{
|
||||
GameObject obj = Detached[i];
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
detachedStates[i] = new DetachedState
|
||||
{
|
||||
obj = obj,
|
||||
originalParent = obj.transform.parent,
|
||||
localPosition = obj.transform.localPosition,
|
||||
localRotation = obj.transform.localRotation,
|
||||
localScale = obj.transform.localScale
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void RestoreDetachedObjects()
|
||||
{
|
||||
if (detachedStates == null || detachedStates.Length == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < detachedStates.Length; i++)
|
||||
{
|
||||
DetachedState state = detachedStates[i];
|
||||
if (state == null || state.obj == null)
|
||||
continue;
|
||||
|
||||
Transform t = state.obj.transform;
|
||||
|
||||
t.SetParent(state.originalParent, false);
|
||||
t.localPosition = state.localPosition;
|
||||
t.localRotation = state.localRotation;
|
||||
t.localScale = state.localScale;
|
||||
|
||||
ParticleSystem[] systems = state.obj.GetComponentsInChildren<ParticleSystem>(true);
|
||||
for (int j = 0; j < systems.Length; j++)
|
||||
{
|
||||
ParticleSystem ps = systems[j];
|
||||
if (ps == null)
|
||||
continue;
|
||||
|
||||
ps.Clear(true);
|
||||
ps.Play(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void StartLifeTimer()
|
||||
{
|
||||
if (lifeRoutine != null)
|
||||
StopCoroutine(lifeRoutine);
|
||||
|
||||
lifeRoutine = StartCoroutine(LifeTimerRoutine(lifeTime));
|
||||
}
|
||||
|
||||
protected virtual IEnumerator LifeTimerRoutine(float time)
|
||||
{
|
||||
yield return new WaitForSeconds(time);
|
||||
|
||||
if (notDestroy)
|
||||
{
|
||||
if (gameObject.activeSelf)
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
if (collided || rb == null || speed == 0f)
|
||||
return;
|
||||
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rb.linearVelocity = transform.forward * speed;
|
||||
#else
|
||||
rb.velocity = transform.forward * speed;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected virtual void OnCollisionEnter(Collision collision)
|
||||
{
|
||||
if (collided)
|
||||
return;
|
||||
|
||||
collided = true;
|
||||
StopRunningCoroutines();
|
||||
|
||||
if (rb != null)
|
||||
{
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
rb.linearVelocity = Vector3.zero;
|
||||
#else
|
||||
rb.velocity = Vector3.zero;
|
||||
#endif
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
rb.constraints = RigidbodyConstraints.FreezeAll;
|
||||
}
|
||||
|
||||
if (lightSourse != null)
|
||||
lightSourse.enabled = false;
|
||||
|
||||
if (col != null)
|
||||
col.enabled = false;
|
||||
|
||||
if (projectilePS != null)
|
||||
projectilePS.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
|
||||
|
||||
if (collision.contactCount > 0)
|
||||
SpawnHit(collision.contacts[0]);
|
||||
|
||||
ReleaseDetachedObjects();
|
||||
|
||||
float endDelay = 1f;
|
||||
if (hitPS != null)
|
||||
endDelay = Mathf.Max(hitPS.main.duration, 0.05f);
|
||||
|
||||
if (notDestroy)
|
||||
disableAfterHitRoutine = StartCoroutine(DisableAfterHit(endDelay));
|
||||
else
|
||||
Destroy(gameObject, endDelay);
|
||||
}
|
||||
|
||||
protected virtual IEnumerator DisableAfterHit(float delay)
|
||||
{
|
||||
yield return new WaitForSeconds(delay);
|
||||
|
||||
if (gameObject != null && gameObject.activeSelf)
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
protected virtual void SpawnHit(ContactPoint contact)
|
||||
{
|
||||
if (hit == null)
|
||||
return;
|
||||
|
||||
Vector3 pos = contact.point + contact.normal * hitOffset;
|
||||
Quaternion rot = Quaternion.FromToRotation(Vector3.up, contact.normal);
|
||||
|
||||
hit.transform.position = pos;
|
||||
hit.transform.rotation = rot;
|
||||
|
||||
if (UseFirePointRotation)
|
||||
hit.transform.rotation = transform.rotation * Quaternion.Euler(0f, 180f, 0f);
|
||||
else if (rotationOffset != Vector3.zero)
|
||||
hit.transform.rotation = Quaternion.Euler(rotationOffset);
|
||||
else
|
||||
hit.transform.LookAt(contact.point + contact.normal);
|
||||
|
||||
if (hitPS != null)
|
||||
{
|
||||
hitPS.Clear(true);
|
||||
hitPS.Play(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ReleaseDetachedObjects()
|
||||
{
|
||||
if (detachedStates == null || detachedStates.Length == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < detachedStates.Length; i++)
|
||||
{
|
||||
DetachedState state = detachedStates[i];
|
||||
if (state == null || state.obj == null)
|
||||
continue;
|
||||
|
||||
Transform t = state.obj.transform;
|
||||
t.SetParent(null, true);
|
||||
|
||||
ParticleSystem[] systems = state.obj.GetComponentsInChildren<ParticleSystem>(true);
|
||||
for (int j = 0; j < systems.Length; j++)
|
||||
{
|
||||
ParticleSystem ps = systems[j];
|
||||
if (ps == null)
|
||||
continue;
|
||||
|
||||
ps.Stop(true, ParticleSystemStopBehavior.StopEmitting);
|
||||
}
|
||||
|
||||
if (!notDestroy)
|
||||
Destroy(state.obj, detachedLifeTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 605a456cfc02f6b499a64717539a27e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/HS_ProjectileMover.cs
|
||||
uploadId: 883376
|
||||
93
Assets/Hovl Studio/HSFiles/Scripts/HS_ProjectileMover2D.cs
Normal file
93
Assets/Hovl Studio/HSFiles/Scripts/HS_ProjectileMover2D.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HS_ProjectileMover2D : MonoBehaviour
|
||||
{
|
||||
public float speed = 15f;
|
||||
public float hitOffset = 0f;
|
||||
public bool UseFirePointRotation;
|
||||
public Vector3 rotationOffset = new Vector3(0, 0, 0);
|
||||
public GameObject hit;
|
||||
public GameObject flash;
|
||||
private Rigidbody2D rb;
|
||||
public GameObject[] Detached;
|
||||
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody2D>();
|
||||
if (flash != null)
|
||||
{
|
||||
//Instantiate flash effect on projectile position
|
||||
var flashInstance = Instantiate(flash, transform.position, Quaternion.identity);
|
||||
flashInstance.transform.forward = gameObject.transform.forward;
|
||||
|
||||
//Destroy flash effect depending on particle Duration time
|
||||
var flashPs = flashInstance.GetComponent<ParticleSystem>();
|
||||
if (flashPs != null)
|
||||
{
|
||||
Destroy(flashInstance, flashPs.main.duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
var flashPsParts = flashInstance.transform.GetChild(0).GetComponent<ParticleSystem>();
|
||||
Destroy(flashInstance, flashPsParts.main.duration);
|
||||
}
|
||||
}
|
||||
Destroy(gameObject,5);
|
||||
}
|
||||
|
||||
void FixedUpdate ()
|
||||
{
|
||||
if (speed != 0)
|
||||
{
|
||||
rb.linearVelocity = transform.forward * speed;
|
||||
//transform.position += transform.forward * (speed * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
//https ://docs.unity3d.com/ScriptReference/Rigidbody.OnCollisionEnter.html
|
||||
void OnCollisionEnter2D(Collision2D collision)
|
||||
{
|
||||
//Lock all axes movement and rotation
|
||||
rb.constraints = RigidbodyConstraints2D.FreezeAll;
|
||||
speed = 0;
|
||||
|
||||
ContactPoint2D contact = collision.contacts[0];
|
||||
Quaternion rot = Quaternion.FromToRotation(Vector3.up, contact.normal);
|
||||
Vector3 pos = contact.point + contact.normal * hitOffset;
|
||||
|
||||
//Spawn hit effect on collision
|
||||
if (hit != null)
|
||||
{
|
||||
var hitInstance = Instantiate(hit, pos, rot);
|
||||
if (UseFirePointRotation) { hitInstance.transform.rotation = gameObject.transform.rotation * Quaternion.Euler(0, 180f, 0); }
|
||||
else if (rotationOffset != Vector3.zero) { hitInstance.transform.rotation = Quaternion.Euler(rotationOffset); }
|
||||
else { hitInstance.transform.LookAt(contact.point + contact.normal); }
|
||||
|
||||
//Destroy hit effects depending on particle Duration time
|
||||
var hitPs = hitInstance.GetComponent<ParticleSystem>();
|
||||
if (hitPs != null)
|
||||
{
|
||||
Destroy(hitInstance, hitPs.main.duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
var hitPsParts = hitInstance.transform.GetChild(0).GetComponent<ParticleSystem>();
|
||||
Destroy(hitInstance, hitPsParts.main.duration);
|
||||
}
|
||||
}
|
||||
|
||||
//Removing trail from the projectile on cillision enter or smooth removing. Detached elements must have "AutoDestroying script"
|
||||
foreach (var detachedPrefab in Detached)
|
||||
{
|
||||
if (detachedPrefab != null)
|
||||
{
|
||||
detachedPrefab.transform.parent = null;
|
||||
Destroy(detachedPrefab, 1);
|
||||
}
|
||||
}
|
||||
//Destroy projectile on collision
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5e49040cdee09a4fbfb8cd6d0cc243d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/HS_ProjectileMover2D.cs
|
||||
uploadId: 883376
|
||||
137
Assets/Hovl Studio/HSFiles/Scripts/HS_TargetProjectile.cs
Normal file
137
Assets/Hovl Studio/HSFiles/Scripts/HS_TargetProjectile.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HS_TargetProjectile : MonoBehaviour
|
||||
{
|
||||
public float speed = 15f;
|
||||
public GameObject hit;
|
||||
public GameObject flash;
|
||||
public GameObject[] Detached;
|
||||
public bool LocalRotation = false;
|
||||
private Transform target;
|
||||
private Vector3 targetOffset;
|
||||
private float startDistanceToTarget;
|
||||
|
||||
[Space]
|
||||
[Header("PROJECTILE PATH")]
|
||||
private float randomUpAngle;
|
||||
private float randomSideAngle;
|
||||
public float sideAngle = 25;
|
||||
public float upAngle = 20;
|
||||
|
||||
void Start()
|
||||
{
|
||||
FlashEffect();
|
||||
newRandom();
|
||||
}
|
||||
|
||||
void newRandom()
|
||||
{
|
||||
randomUpAngle = Random.Range(0, upAngle);
|
||||
randomSideAngle = Random.Range(-sideAngle, sideAngle);
|
||||
}
|
||||
|
||||
//Link from another script
|
||||
//TARGET POSITION + TARGET OFFSET
|
||||
public void UpdateTarget(Transform targetPosition , Vector3 Offset)
|
||||
{
|
||||
target = targetPosition;
|
||||
targetOffset = Offset;
|
||||
startDistanceToTarget = Vector3.Distance((target.position + targetOffset), transform.position);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
foreach (var detachedPrefab in Detached)
|
||||
{
|
||||
if (detachedPrefab != null)
|
||||
{
|
||||
detachedPrefab.transform.parent = null;
|
||||
}
|
||||
}
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
float distanceToTarget = Vector3.Distance((target.position + targetOffset), transform.position);
|
||||
float angleRange = (distanceToTarget - 10) / 60;
|
||||
if (angleRange < 0) angleRange = 0;
|
||||
|
||||
float saturatedDistanceToTarget = (distanceToTarget / startDistanceToTarget);
|
||||
if (saturatedDistanceToTarget < 0.5)
|
||||
saturatedDistanceToTarget -= (0.5f - saturatedDistanceToTarget);
|
||||
saturatedDistanceToTarget -= angleRange;
|
||||
if (saturatedDistanceToTarget <= 0)
|
||||
saturatedDistanceToTarget = 0;
|
||||
|
||||
Vector3 forward = ((target.position + targetOffset) - transform.position);
|
||||
Vector3 crossDirection = Vector3.Cross(forward, Vector3.up);
|
||||
Quaternion randomDeltaRotation = Quaternion.Euler(0, randomSideAngle*saturatedDistanceToTarget, 0) * Quaternion.AngleAxis(randomUpAngle * saturatedDistanceToTarget, crossDirection);
|
||||
Vector3 direction = randomDeltaRotation * forward;
|
||||
|
||||
float distanceThisFrame = Time.deltaTime * speed;
|
||||
|
||||
if (direction.magnitude <= distanceThisFrame)
|
||||
{
|
||||
HitTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
transform.Translate(direction.normalized * distanceThisFrame, Space.World);
|
||||
transform.rotation = Quaternion.LookRotation(direction);
|
||||
}
|
||||
|
||||
void FlashEffect()
|
||||
{
|
||||
if (flash != null)
|
||||
{
|
||||
var flashInstance = Instantiate(flash, transform.position, Quaternion.identity);
|
||||
flashInstance.transform.forward = gameObject.transform.forward;
|
||||
var flashPs = flashInstance.GetComponent<ParticleSystem>();
|
||||
if (flashPs != null)
|
||||
{
|
||||
Destroy(flashInstance, flashPs.main.duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
var flashPsParts = flashInstance.transform.GetChild(0).GetComponent<ParticleSystem>();
|
||||
Destroy(flashInstance, flashPsParts.main.duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HitTarget()
|
||||
{
|
||||
if (hit != null)
|
||||
{
|
||||
var hitRotation = transform.rotation;
|
||||
if (LocalRotation == true)
|
||||
{
|
||||
hitRotation = Quaternion.Euler(0, 0, 0);
|
||||
}
|
||||
var hitInstance = Instantiate(hit, target.position + targetOffset, hitRotation);
|
||||
var hitPs = hitInstance.GetComponent<ParticleSystem>();
|
||||
if (hitPs != null)
|
||||
{
|
||||
Destroy(hitInstance, hitPs.main.duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
var hitPsParts = hitInstance.transform.GetChild(0).GetComponent<ParticleSystem>();
|
||||
Destroy(hitInstance, hitPsParts.main.duration);
|
||||
}
|
||||
}
|
||||
foreach (var detachedPrefab in Detached)
|
||||
{
|
||||
if (detachedPrefab != null)
|
||||
{
|
||||
detachedPrefab.transform.parent = null;
|
||||
Destroy(detachedPrefab, 1);
|
||||
}
|
||||
}
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e24cfb966f425fa47bfec1667489bb42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 315729
|
||||
packageName: BIG Projectiles bundle
|
||||
packageVersion: 3.1
|
||||
assetPath: Assets/Hovl Studio/HSFiles/Scripts/HS_TargetProjectile.cs
|
||||
uploadId: 883376
|
||||
Reference in New Issue
Block a user