-
-
Save yankooliveira/cfd690bac53a60fbe79f53ac54b98b03 to your computer and use it in GitHub Desktop.
Source code for my #1classjam entry, Chimera
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.PostProcessing; | |
using UnityEngine.SceneManagement; | |
using UnityEngine.UI; | |
using Random = UnityEngine.Random; | |
public class Chimera : MonoBehaviour | |
{ | |
public enum EntityType | |
{ | |
None = 0, | |
Brick = 1, | |
Ball = 2, | |
Paddle = 3, | |
Game = 4, | |
Camera = 5, | |
} | |
public enum GameState | |
{ | |
None = 0, | |
MainMenu = 1, | |
WonLevel = 2, | |
LevelPrepare = 3, | |
InGame = 4, | |
GameOver = 5, | |
Glitch = 6, | |
} | |
[Header("Entity")] | |
public EntityType Type; | |
public float Speed; | |
public float Width; | |
public float Height; | |
public int Health = 1; | |
public int Points = 1; | |
public Vector2 MinMaxAngle; | |
[Header("Game Config")] | |
public Chimera TemplateBrick; | |
public Chimera TemplateBall; | |
public Chimera TemplatePaddle; | |
public Vector2 MinMaxVerticalBrickAmount = new Vector2(2, 4); | |
public Vector2 MinMaxHorizontalBrickAmount = new Vector2(2, 7); | |
public AnimationCurve BrickHealthBalancing; | |
public AnimationCurve BrickAmountBalancing; | |
public AnimationCurve BallSpeedBalancing; | |
public AnimationCurve PlatformSpeedBalancing; | |
public AnimationCurve ChanceOfGlitch; | |
[Header("FX")] | |
public GameObject Particles; | |
public GameObject WarpEffects; | |
public float WarpBgDuration = 0.5f; | |
public PostProcessingProfile BgPostProcessor; | |
public Material PostProcessMaterial; | |
public Gradient ColorGradient; | |
[Header("UI")] | |
public GameObject StartUI; | |
public GameObject GameOverUI; | |
public GameObject LevelUI; | |
public Text ScoreText; | |
public Text LivesText; | |
public Text IncomingLevelText; | |
public Text FinalScoreText; | |
[Header("Audio")] | |
public AudioSource MusicSource; | |
public AudioSource SFXSource; | |
public AudioClip SFXGlitch; | |
public AudioClip SFXBall; | |
public AudioClip SFXBallDeath; | |
public AudioClip SFXLevelUp; | |
public AudioClip[] SFXBreak; | |
public event Action<Chimera> EntityDied; | |
public event Action<Chimera> EntityTookDamage; | |
public event Action<Chimera> EntityMutated; | |
private EntityType previousType; | |
public bool HasMutatedOnce | |
{ | |
get { return previousType != EntityType.None && previousType != Type; } | |
} | |
private int brickLayer; | |
private int defaultLayer; | |
private int paddleLayer; | |
private Renderer targetRenderer; | |
private Vector3 originalLocalPosition; | |
private void Awake() | |
{ | |
BuildCaches(); | |
switch (Type) | |
{ | |
case EntityType.Game: SetupGame(); return; | |
} | |
} | |
private void Update() | |
{ | |
switch (Type) | |
{ | |
case EntityType.Ball: UpdateBall(); return; | |
case EntityType.Paddle: UpdatePaddle(); return; | |
case EntityType.Camera: UpdateCamera(); return; | |
case EntityType.Game: UpdateGame(); return; | |
} | |
} | |
private void OnCollisionEnter(Collision collision) | |
{ | |
switch (Type) | |
{ | |
case EntityType.Brick: OnCollisionEnterBrick(collision); return; | |
case EntityType.Ball: OnCollisionEnterBall(collision); return; | |
} | |
} | |
private void BuildCaches() | |
{ | |
brickLayer = LayerMask.NameToLayer("Brick"); | |
defaultLayer = LayerMask.NameToLayer("Default"); | |
paddleLayer = LayerMask.NameToLayer("Paddle"); | |
originalLocalPosition = transform.localPosition; | |
targetRenderer = GetComponent<Renderer>(); | |
// Hardcoding this for bricks because I just don't care anymore | |
if (targetRenderer == null) | |
{ | |
targetRenderer = transform.GetChild(0).GetComponent<Renderer>(); | |
} | |
} | |
private void UpdateMovement() | |
{ | |
transform.position += currentDirection * Speed * Time.deltaTime; | |
} | |
private void Mutate(EntityType type, Material mat = null) | |
{ | |
if (Type == type) return; | |
if (!HasMutatedOnce) | |
{ | |
previousType = Type; | |
} | |
Type = type; | |
switch (type) | |
{ | |
case EntityType.Ball: | |
MutateIntoBall(); | |
break; | |
case EntityType.Brick: | |
gameObject.layer = brickLayer; | |
break; | |
case EntityType.Paddle: | |
gameObject.layer = paddleLayer; | |
break; | |
} | |
if (mat != null && targetRenderer != null) | |
{ | |
targetRenderer.material = mat; | |
} | |
if (EntityMutated != null) | |
{ | |
EntityMutated(this); | |
} | |
} | |
private void MutateIntoBall() | |
{ | |
gameObject.layer = defaultLayer; | |
currentDirection = Random.insideUnitCircle.normalized; | |
GetComponent<Collider>().enabled = false; | |
StartCoroutine(DelayEnableCollider(1f)); | |
} | |
private IEnumerator DelayEnableCollider(float time) | |
{ | |
yield return new WaitForSeconds(time); | |
GetComponent<Collider>().enabled = true; | |
} | |
#region Brick | |
private void SetBrickHealth(int health) | |
{ | |
if (health > 0) | |
{ | |
targetRenderer.material.SetColor("_Color", ColorGradient.Evaluate(health / 10f)); | |
} | |
Health = health; | |
if (EntityTookDamage != null) | |
{ | |
EntityTookDamage(this); | |
} | |
} | |
private void OnCollisionEnterBrick(Collision collision) | |
{ | |
SetBrickHealth(Health - 1); | |
if (Health <= 0) | |
{ | |
if (Particles != null) | |
{ | |
Particles.SetActive(true); | |
} | |
GetComponent<Collider>().enabled = false; | |
transform.GetChild(0).gameObject.SetActive(false); | |
KillEntity(1f); | |
} | |
SFXSource.PlayOneShot(SFXBreak[Random.Range(0, SFXBreak.Length)]); | |
} | |
private void AnimateBrickAppear(float delay = 0f) | |
{ | |
var brickTrans = transform.GetChild(0); | |
brickTrans.localScale = Vector3.zero; | |
StartCoroutine(AnimateBrickAppearRoutine(brickTrans, delay)); | |
} | |
private IEnumerator AnimateBrickAppearRoutine(Transform brickTrans, float delay = 0f) | |
{ | |
if (delay > 0f) | |
{ | |
yield return new WaitForSeconds(delay); | |
} | |
float timer = 0f; | |
while (timer < 0.5f) | |
{ | |
timer += Time.deltaTime; | |
brickTrans.localScale = Vector3.Lerp(brickTrans.localScale, Vector3.one, timer / 0.5f); | |
yield return null; | |
} | |
} | |
#endregion | |
#region Ball | |
private Chimera ball; | |
private Vector3 currentDirection; | |
private void UpdateBall() | |
{ | |
if (!isLevelRunning) | |
{ | |
return; | |
} | |
UpdateMovement(); | |
var ballViewport = Camera.main.WorldToViewportPoint(transform.position); | |
bool collided = false; | |
if (ballViewport.y < 0f) | |
{ | |
if (isGlitching) | |
{ | |
currentDirection.y = 1f; | |
collided = true; | |
} | |
else | |
{ | |
KillEntity(); | |
} | |
} | |
else if (ballViewport.y > 1f) | |
{ | |
currentDirection.y = -1f; | |
collided = true; | |
} | |
if (ballViewport.x < 0f) | |
{ | |
currentDirection.x = 1f; | |
collided = true; | |
} | |
else if (ballViewport.x > 1f) | |
{ | |
currentDirection.x = -1f; | |
collided = true; | |
} | |
if (collided) | |
{ | |
currentDirection.Normalize(); | |
SFXSource.PlayOneShot(SFXBall); | |
} | |
} | |
private void KillEntity(float delay = 0) | |
{ | |
Destroy(gameObject, delay); | |
if (EntityDied != null) | |
{ | |
EntityDied(this); | |
} | |
} | |
private void OnCollisionEnterBall(Collision collision) | |
{ | |
if (collision.contacts[0].point.x > transform.position.x) | |
{ | |
currentDirection.x = -1; | |
} | |
else if (collision.contacts[0].point.x < transform.position.x) | |
{ | |
currentDirection.x = 1; | |
} | |
if (collision.contacts[0].point.y > transform.position.y) | |
{ | |
currentDirection.y = -1f; | |
} | |
else if (collision.contacts[0].point.y < transform.position.y) | |
{ | |
currentDirection.y = 1f; | |
} | |
if (collision.gameObject.layer.Equals(paddleLayer)) | |
{ | |
var paddle = collision.gameObject.GetComponent<Chimera>(); | |
if (paddle.previousType == EntityType.Brick) | |
{ | |
paddle.OnCollisionEnterBrick(collision); | |
} | |
else | |
{ | |
currentDirection.y = 1f; | |
currentDirection.x = paddle.currentDirection.x > 0f ? 1f : -1f; | |
var factor = Mathf.Abs(paddle.rotateFactor / paddle.MinMaxAngle.x); | |
if (factor != 0f) | |
{ | |
currentDirection.x *= factor; | |
} | |
} | |
} | |
currentDirection.Normalize(); | |
if (!collision.collider.gameObject.layer.Equals(brickLayer)) | |
{ | |
SFXSource.PlayOneShot(SFXBall); | |
} | |
} | |
#endregion | |
#region Paddle | |
private Chimera paddle; | |
private float rotateFactor; | |
private void UpdatePaddle() | |
{ | |
if (Input.GetKeyDown(KeyCode.R)) | |
{ | |
SceneManager.LoadScene(0); | |
} | |
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A)) | |
{ | |
currentDirection = Vector3.left; | |
} | |
else if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D)) | |
{ | |
currentDirection = Vector3.right; | |
} | |
else | |
{ | |
currentDirection = Vector3.zero; | |
} | |
UpdateMovement(); | |
float rotateAngle = 0; | |
if (currentDirection.x != 0f) | |
{ | |
rotateAngle = currentDirection.x > 0f ? MinMaxAngle.y : MinMaxAngle.x; | |
} | |
rotateFactor = Mathf.Lerp(rotateFactor, rotateAngle, Time.deltaTime * 5f); | |
transform.rotation = Quaternion.AngleAxis(rotateFactor, Vector3.forward); | |
} | |
private IEnumerator GlitchRoutine() | |
{ | |
isGlitching = true; | |
cameraControl.postprocessorIsEnabled = true; | |
SFXSource.PlayOneShot(SFXGlitch); | |
MusicSource.volume = 0f; | |
yield return new WaitForSeconds(SFXGlitch.length * 0.15f); | |
cameraControl.postprocessorIsEnabled = false; | |
isGlitching = false; | |
yield return new WaitForSeconds(SFXGlitch.length * 0.85f); | |
MusicSource.volume = 1f; | |
} | |
#endregion | |
#region Game | |
private GameState currentGameState; | |
private int currentScore = 0; | |
private int lives = 3; | |
private List<Chimera> currentBricks = new List<Chimera>(); | |
private Vector3 bottomLeftBrick = new Vector3(-7f, 5f, 0f); | |
private Vector3 topRightBrick = new Vector3(7f, 9f, 0f); | |
private int currentHorizontalBrickAmount; | |
private int currentVerticalBrickAmount; | |
private Chimera _cameraControl; | |
private Chimera cameraControl | |
{ | |
get | |
{ | |
if (_cameraControl == null) | |
{ | |
_cameraControl = Camera.main.GetComponent<Chimera>(); | |
} | |
return _cameraControl; | |
} | |
} | |
private static bool isLevelRunning; | |
private static bool isGlitching; | |
private float nextGlitchTimeLock; | |
private int ballCount; | |
private bool isShiningBG = false; | |
private int currentLevel; | |
private void SetupGame() | |
{ | |
WarpEffects = Instantiate(WarpEffects); | |
SetGameState(GameState.MainMenu); | |
} | |
private void PlayerPressedSpace() | |
{ | |
switch (currentGameState) | |
{ | |
case GameState.MainMenu: | |
SetGameState(GameState.LevelPrepare); | |
break; | |
case GameState.LevelPrepare: | |
if (!isLevelRunning) | |
{ | |
SetGameState(GameState.InGame); | |
} | |
break; | |
case GameState.InGame: | |
if (!isLevelRunning) | |
{ | |
isLevelRunning = true; | |
} | |
break; | |
case GameState.GameOver: | |
SceneManager.LoadScene(0); | |
break; | |
} | |
} | |
private void SetGameState(GameState state) | |
{ | |
switch (state) | |
{ | |
case GameState.MainMenu: | |
ShowMainMenu(true); | |
break; | |
case GameState.LevelPrepare: | |
ShowMainMenu(false); | |
ShowLevelPrepare(true); | |
isLevelRunning = false; | |
SFXSource.PlayOneShot(SFXLevelUp); | |
SetupLevel(); | |
ChangeLives(0); | |
break; | |
case GameState.InGame: | |
isLevelRunning = true; | |
ScoreText.enabled = true; | |
ShowLevelPrepare(false); | |
break; | |
case GameState.GameOver: | |
ShowEndGame(true); | |
isLevelRunning = false; | |
FinalScoreText.text = "Final score: " + currentScore.ToString(); | |
ScoreText.enabled = false; | |
break; | |
} | |
currentGameState = state; | |
} | |
private Vector3 GetBrickDimensions() | |
{ | |
float xSize = topRightBrick.x - bottomLeftBrick.x; | |
float x = xSize / (float)currentHorizontalBrickAmount; | |
float ySize = topRightBrick.y - bottomLeftBrick.y; | |
float y = ySize / (float)currentVerticalBrickAmount; | |
return new Vector3(x, y, 1f); | |
} | |
private void SetupLevel() | |
{ | |
if (currentLevel == 0) | |
{ | |
// Don't judge! It's Sunday, I wanna go do something else | |
Invoke("CreatePaddle", 1f); | |
Invoke("CreateBall", 1f); | |
} | |
else | |
{ | |
paddle.Speed = PlatformSpeedBalancing.Evaluate(currentLevel); | |
ball.Speed = BallSpeedBalancing.Evaluate(currentLevel); | |
} | |
CreateBricks(); | |
} | |
private void UpdateGame() | |
{ | |
if (Input.GetKeyDown(KeyCode.Space)) | |
{ | |
PlayerPressedSpace(); | |
} | |
if (Input.GetKeyDown(KeyCode.T)) | |
{ | |
MutateRandomBrick(); | |
} | |
if (Input.GetKeyDown(KeyCode.B)) | |
{ | |
for (int i = currentBricks.Count - 1; i >= 0; i--) | |
{ | |
currentBricks[i].OnCollisionEnterBrick(null); | |
} | |
} | |
if (Input.GetKeyDown(KeyCode.M)) | |
{ | |
SFXSource.enabled = !SFXSource.enabled; | |
MusicSource.enabled = !MusicSource.enabled; | |
} | |
if (!isLevelRunning && ball != null && paddle != null) | |
{ | |
ball.transform.position = paddle.transform.position + new Vector3(0f, 1f, 0f); | |
} | |
} | |
private void CheckForGlitches() | |
{ | |
if (Time.time < nextGlitchTimeLock) | |
{ | |
return; | |
} | |
var chance = ChanceOfGlitch.Evaluate(currentLevel); | |
if (Random.value < chance && isLevelRunning) | |
{ | |
MutateRandomBrick(); | |
nextGlitchTimeLock = Time.time + Random.Range(20f, 40f) + 30f * (1 - chance); | |
} | |
} | |
private void MutateRandomBrick() | |
{ | |
var rnd = Random.Range(0, currentBricks.Count); | |
var ent = Random.value < 0.5f ? EntityType.Paddle : EntityType.Ball; | |
currentBricks[rnd].Mutate(ent, ball.targetRenderer.material); | |
StartCoroutine(GlitchRoutine()); | |
} | |
private void CreateBricks() | |
{ | |
float currentLevelFactor = BrickAmountBalancing.Evaluate(currentLevel); | |
currentVerticalBrickAmount = (int)Mathf.Lerp(MinMaxVerticalBrickAmount.x, MinMaxVerticalBrickAmount.y, currentLevelFactor); | |
currentHorizontalBrickAmount = (int)Mathf.Lerp(MinMaxHorizontalBrickAmount.x, MinMaxHorizontalBrickAmount.y, currentLevelFactor); | |
currentBricks.Clear(); | |
Vector3 brickPos = bottomLeftBrick; | |
float startX = brickPos.x; | |
Chimera newBrick = null; | |
Vector3 brickDimensions = GetBrickDimensions(); | |
for (int i = 0; i <= currentVerticalBrickAmount; i++) | |
{ | |
for (int j = 0; j <= currentHorizontalBrickAmount; j++) | |
{ | |
newBrick = Instantiate(TemplateBrick); | |
newBrick.transform.position = brickPos; | |
newBrick.EntityDied += OnBrickDied; | |
newBrick.EntityMutated += OnEntityMutated; | |
newBrick.EntityTookDamage += OnBrickTookDamage; | |
newBrick.transform.localScale = brickDimensions; | |
newBrick.Width = brickDimensions.x; | |
newBrick.Height = brickDimensions.y; | |
newBrick.AnimateBrickAppear((i + j) * 0.1f); | |
newBrick.SetBrickHealth(GetBrickHealth()); | |
newBrick.Points = newBrick.Health; | |
newBrick.SFXSource = SFXSource; | |
newBrick.SFXBreak = SFXBreak; | |
currentBricks.Add(newBrick); | |
brickPos.x += newBrick.Width; | |
} | |
brickPos.x = startX; | |
brickPos.y += newBrick.Height; | |
} | |
} | |
private int GetBrickHealth() | |
{ | |
float health = 1; | |
var chance = Random.value * currentLevel / 10f; | |
if (chance > 0.5f) | |
{ | |
health = Random.Range(2, BrickHealthBalancing.Evaluate(currentLevel)); | |
} | |
return Mathf.FloorToInt(health); | |
} | |
private void OnBrickTookDamage(Chimera brick) | |
{ | |
cameraControl.StartShaking(10f, 1f / Mathf.Max(brick.Health, 1f), 0.5f); | |
if (currentBricks.Count > 1) | |
{ | |
CheckForGlitches(); | |
} | |
} | |
private void OnBrickDied(Chimera brick) | |
{ | |
currentScore += brick.Points; | |
ScoreText.text = currentScore.ToString(); | |
cameraControl.BlinkBG(); | |
if (currentScore % 100 == 0) | |
{ | |
ChangeLives(1); | |
} | |
currentBricks.Remove(brick); | |
if (currentBricks.Count == 0) | |
{ | |
currentLevel++; | |
SetGameState(GameState.LevelPrepare); | |
} | |
} | |
private void CreateBall() | |
{ | |
ball = Instantiate(TemplateBall); | |
ball.transform.position = new Vector3(0f, 1f); | |
ball.currentDirection = new Vector3(-1f, -1f); | |
ball.EntityDied += OnBallDied; | |
ball.EntityMutated += OnEntityMutated; | |
ball.SFXSource = SFXSource; | |
ball.SFXBall = SFXBall; | |
ball.Speed = BallSpeedBalancing.Evaluate(currentLevel); | |
ballCount++; | |
} | |
private void OnBallDied(Chimera ball) | |
{ | |
ballCount--; | |
if (ballCount == 0) | |
{ | |
WarpBG(); | |
} | |
SFXSource.PlayOneShot(SFXBallDeath); | |
ChangeLives(-1); | |
if (lives <= 0) | |
{ | |
SetGameState(GameState.GameOver); | |
} | |
else | |
{ | |
CreateBall(); | |
isLevelRunning = false; | |
} | |
} | |
private void ChangeLives(int delta) | |
{ | |
lives += delta; | |
if (delta > 0) | |
{ | |
SFXSource.PlayOneShot(SFXLevelUp); | |
} | |
// I'm not even ashamed right now | |
LivesText.text = Mathf.Pow(10, lives).ToString().Replace("1", ""); | |
} | |
private void CreatePaddle() | |
{ | |
paddle = Instantiate(TemplatePaddle); | |
paddle.transform.position = Vector3.zero; | |
paddle.transform.localScale = new Vector3(paddle.Width, paddle.Height, 1f); | |
paddle.Speed = PlatformSpeedBalancing.Evaluate(currentLevel); | |
paddle.EntityMutated += OnEntityMutated; | |
} | |
private void OnEntityMutated(Chimera entity) | |
{ | |
if (entity.previousType == EntityType.Ball) | |
{ | |
ballCount--; | |
} | |
if (entity.Type == EntityType.Ball) | |
{ | |
ballCount++; | |
} | |
} | |
private void WarpBG() | |
{ | |
StartCoroutine(ShineBGRoutine(50f, true)); | |
} | |
private void BlinkBG() | |
{ | |
StartCoroutine(ShineBGRoutine(5f, false)); | |
} | |
private IEnumerator ShineBGRoutine(float intensity, bool warp = false) | |
{ | |
if (!isShiningBG) | |
{ | |
isShiningBG = true; | |
if (warp) | |
{ | |
WarpEffects.SetActive(true); | |
} | |
var bloom = BgPostProcessor.bloom.settings; | |
float bloomOrigIntensity = bloom.bloom.intensity; | |
float bloomTargetIntensity = bloom.bloom.intensity = intensity; | |
float timer = 0f; | |
BgPostProcessor.bloom.settings = bloom; | |
while (timer < WarpBgDuration) | |
{ | |
timer += Time.deltaTime; | |
bloom.bloom.intensity = Mathf.Lerp(bloomTargetIntensity, bloomOrigIntensity, timer / WarpBgDuration); | |
BgPostProcessor.bloom.settings = bloom; | |
yield return null; | |
} | |
bloom.bloom.intensity = bloomOrigIntensity; | |
BgPostProcessor.bloom.settings = bloom; | |
if (warp) | |
{ | |
WarpEffects.SetActive(false); | |
} | |
isShiningBG = false; | |
} | |
} | |
private void ShowMainMenu(bool show) | |
{ | |
StartUI.gameObject.SetActive(show); | |
} | |
private void ShowLevelPrepare(bool show) | |
{ | |
if (show) | |
{ | |
if (currentLevel > 0) | |
{ | |
LevelUI.SetActive(true); | |
IncomingLevelText.text = "Level " + (currentLevel + 1).ToString(); | |
} | |
} | |
else | |
{ | |
LevelUI.SetActive(false); | |
} | |
} | |
private void ShowEndGame(bool show) | |
{ | |
GameOverUI.gameObject.SetActive(show); | |
} | |
#endregion | |
#region Camera | |
private bool isShaking; | |
private float lastShakeFrequency; | |
private float lastShakeMagnitude; | |
public bool postprocessorIsEnabled; | |
private void OnRenderImage(RenderTexture source, RenderTexture destination) | |
{ | |
if (postprocessorIsEnabled) | |
{ | |
Graphics.Blit(source, destination, PostProcessMaterial); | |
} | |
else | |
{ | |
Graphics.Blit(source, destination); | |
} | |
} | |
private void UpdateCamera() | |
{ | |
if (isShaking) | |
{ | |
var shake = PerlinShake(lastShakeFrequency, lastShakeMagnitude); | |
transform.localPosition = originalLocalPosition + new Vector3(shake.x, shake.y); | |
} | |
} | |
public void StartShaking(float frequency, float magnitude, float duration = -1) | |
{ | |
isShaking = true; | |
lastShakeFrequency = frequency; | |
lastShakeMagnitude = magnitude; | |
if (duration > 0f) | |
{ | |
// DON'T JUDGE, IT'S 4:43AM! | |
Invoke("StopShaking", duration); | |
} | |
} | |
public void StopShaking() | |
{ | |
isShaking = false; | |
transform.position = originalLocalPosition; | |
} | |
// From http://devblog.aliasinggames.com/camera-shake-earthquake-effect/ | |
public Vector2 PerlinShake(float frequency, float magnitude) | |
{ | |
Vector2 result; | |
float seed = Time.time * frequency; | |
result.x = Mathf.Clamp01(Mathf.PerlinNoise(seed, 0f)) - 0.5f; | |
result.y = Mathf.Clamp01(Mathf.PerlinNoise(0f, seed)) - 0.5f; | |
result = result * magnitude; | |
return result; | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment