Skip to content

Commit

Permalink
Merge pull request #26 from SUSTech-CANStudio/current-work
Browse files Browse the repository at this point in the history
Current work
  • Loading branch information
IF-ACT authored Jan 31, 2021
2 parents d0040fc + 6b75ca3 commit 33d885e
Show file tree
Hide file tree
Showing 24 changed files with 275 additions and 320 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using UnityEngine;

namespace CANStudio.BulletStorm.BulletSystem
{
/// <summary>
/// All accessible parameters of a bullet in <see cref="IBulletController"/>.
/// </summary>
public struct BulletParam
{
/// <summary>
/// Rotation is also the speed direction of a bullet.
/// </summary>
public Quaternion rotation;

/// <summary>
/// Position in world space.
/// </summary>
public Vector3 position;

/// <summary>
/// Speed of the bullet, negative values represents a velocity towards negative direction.
/// </summary>
public float speed;

/// <summary>
/// Scaled time from emission.
/// </summary>
public readonly float lifetime;

internal BulletParam(Quaternion rotation, Vector3 position, float speed, float lifetime)
{
this.rotation = rotation;
this.position = position;
this.speed = speed;
this.lifetime = lifetime;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ public abstract class BulletSystemBase : MonoBehaviour, IBulletSystem, IBulletCo
private AroundAxisModule aroundAxis;

public virtual string Name => name;
public Quaternion Rotation { get => transform.rotation; set => transform.rotation = value; }
public abstract void ChangePosition(Func<Vector3, Vector3, Vector3> operation);
public abstract void ChangeVelocity(Func<Vector3, Vector3, Vector3> operation);
public abstract void ChangeParam(Func<BulletParam, BulletParam> operation);
public abstract void Emit(BulletEmitParam emitParam, Transform emitter);
public abstract void Destroy();
public virtual IBulletController GetController() => Instantiate(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,41 @@ namespace CANStudio.BulletStorm.BulletSystem
[DisallowMultipleComponent]
public class GameObjectBullet : MonoBehaviour
{
public Vector3 velocity;
public float speed;
public float lifetime;
private bool enableLifetime;
public float StartTime { get; private set; }

public void EnableLifeTime(float time)
{
enableLifetime = true;
lifetime = time;
}

internal void Init(Vector3 position, Vector3 velocity)
{
Init(position, velocity, Color.clear, Vector3.zero);
}
internal void Init(Vector3 position, Vector3 velocity) => Init(position, velocity, Color.clear, Vector3.zero);

internal void Init(Vector3 position, Vector3 velocity, Color color, Vector3 size)
{
var t = transform;
t.position = position;
this.velocity = velocity;
speed = velocity.magnitude;
t.forward = velocity;
enableLifetime = false;
if (color != Color.clear) GetComponent<Renderer>().material.color = color;
if (size != Vector3.zero) transform.localScale = size;
}


private void Start()
{
StartTime = Time.time;
}

private void LateUpdate()
{
transform.position += velocity * Time.deltaTime;
var t = transform;
t.position += speed * Time.deltaTime * t.forward;
if (!enableLifetime) return;
lifetime -= Time.deltaTime;
if (lifetime <= 0) Destroy(this);
if (lifetime <= Time.time - StartTime) Destroy(gameObject);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using CANStudio.BulletStorm.Emission;
using CANStudio.BulletStorm.Util;
using UnityEngine;

#pragma warning disable 0649
Expand All @@ -13,7 +14,7 @@ namespace CANStudio.BulletStorm.BulletSystem
/// A bullet system based on <see cref="GameObject"/>. It emits game objects as bullets,
/// and keeps them moving. The bullet system will attach a <see cref="GameObjectBullet"/>
/// component to every game objects it emits, from which you can get bullet attributes like
/// <see cref="GameObjectBullet.velocity"/> and <see cref="GameObjectBullet.lifetime"/>.
/// <see cref="GameObjectBullet.speed"/> and <see cref="GameObjectBullet.lifetime"/>.
/// <para/>
/// This bullet system is much more inefficient than <see cref="ParticleBulletSystem"/>, but
/// useful when you need more flexibility. For example, if you need an enemy bullet which is
Expand All @@ -39,9 +40,8 @@ public override void ChangePosition(Func<Vector3, Vector3, Vector3> operation)
ClearDestroyedBullets();
foreach (var gameObjectBullet in bullets)
{
var bulletTransform = gameObjectBullet.transform;
bulletTransform.position =
operation(bulletTransform.position, gameObjectBullet.velocity);
var t = gameObjectBullet.transform;
t.position = operation(t.position, t.forward * gameObjectBullet.speed);
}
}

Expand All @@ -50,13 +50,30 @@ public override void ChangeVelocity(Func<Vector3, Vector3, Vector3> operation)
ClearDestroyedBullets();
foreach (var gameObjectBullet in bullets)
{
gameObjectBullet.velocity = operation(gameObjectBullet.transform.position, gameObjectBullet.velocity);
var t = gameObjectBullet.transform;
var velocity = operation(t.position, t.forward * gameObjectBullet.speed);
t.forward = velocity.Normalized();
gameObjectBullet.speed = velocity.magnitude;
}
}

public override void ChangeParam(Func<BulletParam, BulletParam> operation)
{
ClearDestroyedBullets();
foreach (var gameObjectBullet in bullets)
{
var t = gameObjectBullet.transform;
var param = operation(new BulletParam(t.rotation, t.position, gameObjectBullet.speed,
Time.time - gameObjectBullet.StartTime));
t.SetPositionAndRotation(param.position, param.rotation);
gameObjectBullet.speed = param.speed;
}
}

public override void Emit(BulletEmitParam emitParam, Transform emitter)
{
var bulletComponent = Instantiate(bullet).AddComponent<GameObjectBullet>();
bullets.Add(bulletComponent);
var absEmitParam = emitParam.RelativeTo(emitter);
bulletComponent.Init(absEmitParam.position, absEmitParam.velocity, absEmitParam.color, absEmitParam.size);
if (enableLifetime) bulletComponent.EnableLifeTime(bulletLifeTime);
Expand All @@ -76,7 +93,7 @@ private IEnumerator WaitForDestroy()
if (bullets is null || bullets.Count == 0) break;
yield return null;
}
Destroy(this);
Destroy(gameObject);
}

/// <summary>
Expand All @@ -93,11 +110,5 @@ private void LateUpdate()
{
bulletsCleared = false;
}

private void OnDestroy()
{
ClearDestroyedBullets();
foreach (var gameObjectBullet in bullets) Destroy(gameObjectBullet);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,28 @@ namespace CANStudio.BulletStorm.BulletSystem
{
public interface IBulletController
{
Quaternion Rotation { get; set; }

/// <summary>
/// Changes all bullets' position in the controller.
/// </summary>
/// <param name="operation">Vector3 ChangedPosition(Vector3 oldPosition, Vector3 oldVelocity)</param>
[Obsolete("Use ChangeParam() instead")]
void ChangePosition(Func<Vector3, Vector3, Vector3> operation);

/// <summary>
/// Changes all bullets' velocity in the controller.
/// </summary>
/// <param name="operation">Vector3 ChangedVelocity(Vector3 oldPosition, Vector3 oldVelocity)</param>
[Obsolete("Use ChangeParam() instead")]
void ChangeVelocity(Func<Vector3, Vector3, Vector3> operation);

/// <summary>
/// Changes all bullets' parameters in the controller.
/// Notice that the readonly value <see cref="BulletParam.lifetime"/> won't be changed by this function.
/// </summary>
/// <param name="operation"></param>
void ChangeParam(Func<BulletParam, BulletParam> operation);

/// <summary>
/// Emits a new bullet from the controller.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ public void OnUpdate(IBulletController controller)
var acc = acceleration;
var min = minSpeed;
var max = maxSpeed;
controller.ChangeVelocity((oldPosition, oldVelocity) =>
controller.ChangeParam(param =>
{
var speed = oldVelocity.magnitude + acc * deltaTime;
var speed = param.speed + acc * deltaTime;
if (acc < 0 && speed < min) speed = min;
else if (acc > 0 && speed > max) speed = max;
return oldVelocity.SafeChangeMagnitude(speed);
param.speed = speed;
return param;
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using CANStudio.BulletStorm.Util;
using NaughtyAttributes;
using UnityEngine;

#pragma warning disable 0649
Expand All @@ -10,11 +9,12 @@ namespace CANStudio.BulletStorm.BulletSystem.Modules
[Serializable]
public struct AroundAxisModule
{
[InfoBox("This module is experimental, your configure may loss when updating to next version.", EInfoBoxType.Warning)]

[Tooltip("Rotates around this axis."), SerializeField]
private Vector3 axis;

[Tooltip("If select 'self', use reference system set in emitter."), SerializeField]
private Space space;

[Tooltip("Per second rotation angle in degree."), SerializeField]
private float anglePerSecond;

Expand All @@ -25,13 +25,24 @@ public void OnUpdate(IBulletController controller)
BulletStormLogger.LogErrorOnce($"{controller}: In Around axis module, axis can't be zero!");
return;
}
var ax = axis;

Vector3 axisInWorld;
switch (space)
{
case Space.World:
axisInWorld = axis;
break;
case Space.Self:
axisInWorld = controller.Rotation * axis;
break;
default:
throw new ArgumentOutOfRangeException();
}
var angle = anglePerSecond * Time.deltaTime;
controller.ChangeVelocity((oldPosition, oldVelocity) =>
controller.ChangeParam(param =>
{
var forward = Vector3.Project(oldVelocity, ax);
var projection = Vector3.ProjectOnPlane(oldVelocity, ax);
return forward + Quaternion.AngleAxis(angle, ax) * projection;
param.rotation = Quaternion.AngleAxis(angle, axisInWorld) * param.rotation;
return param;
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using CANStudio.BulletStorm.Util;
using NaughtyAttributes;
using UnityEngine;

#pragma warning disable 0649
Expand All @@ -13,67 +12,16 @@ public struct DeflectionModule
[Tooltip("Velocity deflection angle per second."), SerializeField]
private Vector2 deflection;

[Tooltip("Specific the space that deflection calculated in."), SerializeField]
private Space space;

[Tooltip("The target transform to be a space."), SerializeField, ShowIf(nameof(ShowTarget)), AllowNesting]
private TargetWrapper target;

[Space, Space] // fix the AllowNesting attribute's default behavior

[Tooltip("The euler to describe rotation of a space."), SerializeField, ShowIf(nameof(ShowEuler)), AllowNesting]
private Vector3 euler;

private bool ShowEuler => space == Space.Fixed;
private bool ShowTarget => space == Space.Dynamic;

public void OnUpdate(IBulletController controller)
{
Quaternion rotation;

var dEuler = new Vector3(-deflection.y * Time.deltaTime, deflection.x * Time.deltaTime);

switch (space)
{
case Space.World:
rotation = Quaternion.Euler(dEuler);
break;
case Space.Fixed:
rotation = Helpers.Euler(dEuler, Quaternion.Euler(euler));
break;
case Space.Dynamic:
if (!target.target.Check())
{
BulletStormLogger.LogWarningOnce($"{controller}: Can't find space {target}, use world space by default.");
rotation = Quaternion.Euler(dEuler);
}
else
{
rotation = Helpers.Euler(dEuler, target.target.AsTransform.rotation);
}
break;
default:
throw new ArgumentOutOfRangeException();
}

controller.ChangeVelocity((oldPosition, oldVelocity) => rotation * oldVelocity);
}

[Serializable]
private enum Space
{
[Tooltip("Simulates in world space.")]
World,
[Tooltip("Take given euler as simulating space.")]
Fixed,
[Tooltip("Take given target as simulating space.")]
Dynamic
}
var rotation = Quaternion.Euler(dEuler);

[Serializable]
private struct TargetWrapper
{
public Target target;
controller.ChangeParam(param =>
{
param.rotation = rotation * param.rotation;
return param;
});
}
}
}
Loading

0 comments on commit 33d885e

Please sign in to comment.