public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { if (burnTimeLeft <= 0) { return; } float t = 1f - burnTimeLeft / totalBurnTime; // normalized time Func <float, float> f_sin = (float s) => Mathf.Sin(s * Mathf.PI); Func <float, float> f_parab = (float s) => 1 - (s - 1) * (s - 1); Func <float, float, float> f_skewedSin = (float s, float skew) => f_sin(Mathf.Lerp(t, f_parab(t), skew)); t = f_skewedSin(t, 0.5f); moveForce.airMove = sensors.upVector * maxThrust * t; burnTimeLeft -= Time.fixedDeltaTime; moveForce.tiltAngle = 25f * input.move; moveForce.tiltStrength = 0.2f; moveForce.airDrag = 1f; moveForce.airMove += sensors.forwardVector * input.move * 120f; moveForce.airForcesSet = true; if (burnTimeLeft <= 0) { burnTimeLeft = 0f; Debug.Log("Jetpack done"); } }
public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { bool belowMagnetic = sensors.localBelowCeiling && sensors.localBelowCeilingCollider.tag == "magnetic"; const float magnetStrengthMax = 400f; const float magnetStrengthMin = 10f; const float magnetDist = 12f; if (belowMagnetic) { lineRenderer.enabled = true; lineRenderer.positionCount = 2; lineRenderer.SetPositions(new Vector3[2] { transform.position, sensors.localBelowCeilingPoint }); float t = Mathf.Clamp01((magnetDist - sensors.localCeilingDist) / magnetDist); Vector3 magnetForce = sensors.upVector * Mathf.Lerp(magnetStrengthMin, magnetStrengthMax, t); moveForce.airMove += magnetForce; Debug.Log("Magnet force: " + magnetForce); } else { lineRenderer.positionCount = 0; lineRenderer.enabled = false; } moveForce.airForcesSet = true; }
public override void UpdateKoboto(Koboto koboto, KobotoSensor sensors) { float rollVol = 0f; if (sensors.onGround) { rollVol = Mathf.Clamp01(sensors.velocity.magnitude / 10f); } koboto.soundPlayer.PlayRoll(rollVol); }
protected override void UpdateSensor(KobotoSensor kSense, Vector2 pointInZone) { float strength = (1f - pointInZone.x * pointInZone.x) * windSpeed; float velComp = Mathf.Clamp(Vector3.Dot(kSense.velocity, transform.forward), 0, strength); strength = strength - velComp; Debug.Log("wind strength " + strength); kSense.windSpeed += transform.forward * strength; }
public bool AffectKobotoSenses(KobotoSensor kSense, Vector3 testPoint) { Vector2 pointInZone = Vector2.zero; bool inZone = Test(testPoint, ref pointInZone); if (inZone) { Debug.Log("In zone: " + pointInZone); UpdateSensor(kSense, pointInZone); } return(inZone); }
public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { // m/s to degrees/s const float degreesPerSecMultiplier = 180f / (Mathf.PI * wheelRadius); float targetV = input.move * parameters.groundMoveSpeed; float targetWheelSpeed = targetV; if (sensors.onGround) { // moveForce.airDrag = 0f; moveForce.dynamicFriction = 0f; moveForce.staticFriction = 0f; float groundV = Vector3.Dot(sensors.forwardWheelForward, sensors.velocity); float forceMultiplier = 1f; if (Mathf.Sign(targetV) == Mathf.Sign(groundV)) { float t = Mathf.Clamp01(Mathf.Abs(groundV) / parameters.groundMoveSpeed); forceMultiplier = parameters.groundAccelerationCurve.Evaluate(t); } Vector3 driveForce = forceMultiplier * input.move * parameters.groundMoveStength * sensors.forwardWheelForward; moveForce.groundMove += driveForce; moveForce.upRotation = Utils.TiltFromUpVector(sensors.forwardWheelNormal); moveForce.tiltAngle = 0f; moveForce.tiltStrength = 1f; moveForce.groundForcesSet = true; float groundWheelSpeed = Vector3.Dot(sensors.velocity, sensors.forwardWheelForward); float spinFactor = Mathf.Abs(targetWheelSpeed) * Mathf.Abs((targetWheelSpeed - groundWheelSpeed)); float minSpin = 0.1f; float maxSpin = 8f; wheelSpeed = Mathf.Lerp(groundWheelSpeed, targetWheelSpeed, Utils.Smoothstep(minSpin, maxSpin, spinFactor)) * degreesPerSecMultiplier; } else { moveForce.airTiltResponse = Mathf.Clamp01(sensors.inAirTime * 2f); moveForce.airMoveResponse = 1f; moveForce.upRotation = Quaternion.identity; wheelSpeed = targetWheelSpeed * degreesPerSecMultiplier * 1.5f; } }
public override void UpdateKoboto(Koboto koboto, KobotoSensor sensors) { float rollVol = 0f; if (sensors.onGround) { rollVol = Mathf.Clamp01(sensors.velocity.magnitude / 10f); } koboto.soundPlayer.PlayRoll(rollVol); foreach (var spoke in spokeTransforms) { Debug.Log("Rotating wheel: " + wheelSpeed); spoke.Rotate(Vector3.right, wheelSpeed * Time.fixedDeltaTime); } }
public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { if (!open) { return; } float speedError = terminalVelocity - sensors.velocity.y; float upDragForce = dragControl.Update(speedError, Time.fixedDeltaTime); // float upDragForce = 15f; // Debug.Log("Up force " + upDragForce); moveForce.tiltAngle = 25f * input.move; moveForce.tiltStrength = 0.2f; moveForce.airDrag = 1f; moveForce.airMove += Vector3.up * upDragForce + sensors.forwardVector * input.move * 120f; moveForce.airMove += sensors.windSpeed; moveForce.airForcesSet = true; }
protected override void Init(EGameState gameState) { parameters = GetComponent <KobotoParameters>(); soundPlayer = GetComponent <KobotoSoundPlayer> (); rotationController = new PIDController(tiltControllerP, tiltControllerI, tiltControllerD); sensors = new KobotoSensor(); moveForce = new KobotoMoveForce(); colliderBaseCenter = boxCollider.center; colliderBaseSize = boxCollider.size; physMat = boxCollider.material; capsuleCollider.sharedMaterial = boxCollider.sharedMaterial; physMat.name = "KobotoPhysMat"; upRotation = Quaternion.identity; tiltAngle = 0f; defaultCom = rb.centerOfMass; attachmentTargetContents = new Dictionary <EAttachmentTarget, AttachmentBase>(); attachmentTargetLookup = new Dictionary <EAttachmentTarget, Transform>(); currentAttachments = new Dictionary <EAttachmentType, AttachmentBase>(); var attachPoints = GetComponentsInChildren <KobotoAttachPoint>(); foreach (var point in attachPoints) { attachmentTargetLookup.Add(point.targetType, point.transform); } doFixedUpdate = (gameState == EGameState.Play); SetupCollider(); defaultParent = transform.parent; Debug.Log("Koboto init in state: " + gameState); }
public override void UpdateKoboto(Koboto koboto, KobotoSensor sensor) { base.UpdateKoboto(koboto, sensor); bool shouldOpen = false; bool shouldClose = false; shouldClose |= sensor.onGround; shouldClose |= sensor.onCeiling; shouldClose |= sensor.velocity.y > 0f; shouldOpen = !shouldClose && sensor.velocity.y < downSpeedForOpen; // Debug.Log("speed " + sensor.velocity.y + " should open " + shouldOpen + " should close " + shouldClose); if (!open && shouldOpen) { Open(koboto); } else if (open && shouldClose) { Close(koboto); } }
public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { bool wasOverGround = overGround; bool overGroundLocal = sensors.localAboveGround && sensors.localGroundDist < maxHeight; bool overGroundVertical = sensors.aboveGround && sensors.heightAboveGround < maxHeight; overGround = overGroundLocal || overGroundVertical; if (overGround) { Vector3 point; if (overGround && overGroundLocal) { point = (sensors.aboveGroundPoint + sensors.localAboveGroundPoint) * 0.5f; } else { point = overGroundLocal ? sensors.localAboveGroundPoint : sensors.aboveGroundPoint; } if (!wasOverGround) { groundPoint = point; } else { groundPoint = Vector3.Lerp(groundPoint, point, 4f * Time.fixedDeltaTime); } groundVector = groundPoint - sensors.positionTrail[0]; float height = groundVector.magnitude; dustVFX.transform.position = groundPoint; dustVFX.SetActive(true); float heightError = targetHeight - height; if (resetMotor) { motorControl.Reset(heightError); resetMotor = false; } motorForce = motorControl.Update(heightError, Time.fixedDeltaTime); float propSpeed = Mathf.Clamp01(motorForce / 100f); bladeSpeed = Mathf.Lerp(visualBladeSpeedMin, visualBladeSpeedMax, propSpeed); moveForce.tiltAngle = 45f * input.move; moveForce.tiltStrength = 0.4f; } else { motorForce *= 1f - 0.2f * visualBladeSpeedSlowdown * Time.fixedDeltaTime; bladeSpeed *= 1f - visualBladeSpeedSlowdown * Time.fixedDeltaTime; dustVFX.SetActive(false); } moveForce.airMove = motorForce * strength * sensors.upVector; float glide = Mathf.Abs(Vector3.Dot(sensors.velocity, sensors.forwardVector)); glide = Mathf.Clamp(glide, 0, 6f); Vector3 liftForce = glide * lift * sensors.upVector; moveForce.airMove += liftForce; moveForce.airForcesSet = true; bladeTransform.Rotate(Vector3.up * bladeSpeed, Space.Self); }
protected virtual void ApplyStandardModification(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { }
protected virtual void UpdateSensor(KobotoSensor kSense, Vector2 pointInZone) { }
protected override void UpdateSensor(KobotoSensor kSense, Vector2 pointInZone) { kSense.cameraPushOut = camDistance; }
public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { if (sensors.onGround) { if (firstBounce) { charging = true; bounceVelNormal = preferredBounceSpeed * 0.8f; bounceVelTangent = 0f; landingRotation = Utils.TiltFromUpVector(sensors.groundNormal); } else if (!charging && sensors.landedThisFrame) { charging = true; Debug.Log("Land " + sensors.velocity); landingRotation = Utils.TiltFromUpVector(sensors.upVector); if (sensors.positionTrail.Count < 2) { bounceVelNormal = preferredBounceSpeed * 0.8f; bounceVelTangent = 0f; } else { Vector3 incoming = sensors.velocity; bounceVelNormal = Vector3.Dot(-incoming, sensors.groundNormal); bounceVelTangent = 0.35f * Vector3.Dot(incoming, sensors.groundForward); float speed = incoming.magnitude; bounceVelNormal = Mathf.Lerp(speed, preferredBounceSpeed, 0.8f); } } moveForce.groundMove = Vector3.zero; moveForce.airMove = Vector3.zero; moveForce.upRotation = Utils.TiltFromUpVector(sensors.groundNormal); if (charging && sensors.onGroundTime >= onGroundTime) { // Bounce! charging = false; firstBounce = false; moveForce.airMove = sensors.upVector * bounceVelNormal + sensors.groundForward * bounceVelTangent; moveForce.forceMode = ForceMode.VelocityChange; } else { moveForce.dynamicFriction = 1f; moveForce.staticFriction = 1f; moveForce.upRotation = landingRotation; moveForce.tiltStrength = 1f; } } else { moveForce.airMoveResponse = 1.5f; moveForce.airTiltResponse = 0.8f; } }
public override void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { if (sensors.onGround) { // moveForce.airDrag = 0f; moveForce.dynamicFriction = 0f; moveForce.staticFriction = 0f; float groundV = Vector3.Dot(sensors.forwardWheelForward, sensors.velocity); float targetV = input.move * parameters.groundMoveSpeed; float forceMultiplier = 1f; if (Mathf.Sign(targetV) == Mathf.Sign(groundV)) { float t = Mathf.Clamp01(Mathf.Abs(groundV) / parameters.groundMoveSpeed); forceMultiplier = parameters.groundAccelerationCurve.Evaluate(t); } Vector3 driveForce = forceMultiplier * input.move * parameters.groundMoveStength * sensors.forwardWheelForward; moveForce.groundMove += driveForce; moveForce.upRotation = Utils.TiltFromUpVector(sensors.forwardWheelNormal); moveForce.tiltAngle = 0f; moveForce.tiltStrength = 1f; moveForce.groundForcesSet = true; } else if (sensors.onCeiling) { // moveForce.airDrag = 0f; moveForce.dynamicFriction = 0f; moveForce.staticFriction = 0f; float groundV = Vector3.Dot(sensors.topForwardWheelForward, sensors.velocity); float targetV = input.move * parameters.groundMoveSpeed; float forceMultiplier = 1f; if (Mathf.Sign(targetV) == Mathf.Sign(groundV)) { float t = Mathf.Clamp01(Mathf.Abs(groundV) / parameters.groundMoveSpeed); forceMultiplier = parameters.groundAccelerationCurve.Evaluate(t); } Vector3 driveForce = forceMultiplier * input.move * parameters.groundMoveStength * sensors.topForwardWheelForward; moveForce.groundMove += driveForce; moveForce.upRotation = Utils.TiltFromUpVector(-sensors.topForwardWheelNormal); moveForce.tiltAngle = 0f; moveForce.tiltStrength = 1f; moveForce.groundForcesSet = true; moveForce.airMove = -sensors.topForwardWheelNormal * maxUpForce; moveForce.airForcesSet = true; moveForce.useGravity = false; } else { //if (sensors.belowCeiling && sensors.belowCeilingDist < 1.5f) //{ // Debug.Log("Near ceiling"); // moveForce.upRotation = Utils.TiltFromUpVector(-sensors.topForwardWheelNormal); // moveForce.tiltAngle = 0f; // moveForce.tiltStrength = 1f - sensors.belowCeilingDist / 1.5f; // moveForce.useGravity = false; // moveForce.airForcesSet = true; //} //else { moveForce.alignToCeiling = true; } //moveForce.airTiltResponse = 0.5f * Mathf.Clamp01(sensors.inAirTime - 0.5f); //moveForce.airMoveResponse = 1f; } }
public virtual void ModifyMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { }
public void ProcessMoveForce(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { if (sensors.onGround) { if (!moveForce.groundForcesSet) { moveForce.upRotation = Utils.TiltFromUpVector(sensors.groundNormal); moveForce.tiltAngle = 0f; moveForce.tiltStrength = 1f; } } else { if (!moveForce.airForcesSet) { float alignToGroundStartDist = Mathf.Min(0.75f + 0.25f * sensors.velocity.magnitude, 3f); const float alignToGroundEndDist = 0.5f; Debug.Log("align start " + alignToGroundStartDist); const float alignToCeilingStartDist = 5f; const float alignToCeilingEndDist = 2f; float speed = sensors.velocity.magnitude; // float alignStart = alignToGroundStartDist; // float alignEnd = alignToGroundEndDist; if (moveForce.alignToCeiling && sensors.inAirTime > 0f && speed > 0.1f && sensors.closeToCeiling && sensors.distanceToCeiling < alignToCeilingStartDist && Vector3.Dot(sensors.velocity.normalized, sensors.closestCeilingNormal) < 0f) { Quaternion ceilingAlign = Utils.TiltFromUpVector(-sensors.closestCeilingNormal); Quaternion currentRot = Utils.TiltFromUpVector(sensors.upVector); if (sensors.distanceToCeiling > alignToCeilingEndDist) { ceilingAlign = Quaternion.Lerp(currentRot, ceilingAlign, 24f * Time.fixedDeltaTime); } float t = Mathf.Clamp01((alignToCeilingStartDist - sensors.distanceToCeiling) / (alignToCeilingStartDist - alignToCeilingEndDist)); moveForce.upRotation = Quaternion.Lerp(sensors.airBaseRotation, ceilingAlign, t); moveForce.tiltStrength = Mathf.Clamp01(1f - 8f * t); moveForce.useGravity = false; moveForce.airMove += 20.0f * t * -sensors.closestCeilingNormal; Debug.DrawRay(sensors.closestCeilingPoint, -3.0f * sensors.closestCeilingNormal, Color.yellow); } //align to ground if headed towards it else if (sensors.inAirTime > 0.5f && speed > 0.1f && sensors.closeToGround && sensors.distanceToGround < alignToGroundStartDist && Vector3.Dot(sensors.velocity.normalized, sensors.closestGroundNormal) < 0.1f) { Quaternion groundAlign = Utils.TiltFromUpVector(sensors.closestGroundNormal); Quaternion currentRot = Utils.TiltFromUpVector(sensors.upVector); if (sensors.distanceToGround > alignToGroundEndDist) { groundAlign = Quaternion.Lerp(currentRot, groundAlign, 8f * Time.fixedDeltaTime); } float t = Mathf.Clamp01((alignToGroundStartDist - sensors.distanceToGround) / (alignToGroundStartDist - alignToGroundEndDist)); moveForce.upRotation = Quaternion.Lerp(sensors.airBaseRotation, groundAlign, t); moveForce.tiltStrength = Mathf.Clamp01(1f - 4f * t); Debug.DrawLine(sensors.closestGroundPoint, sensors.closestGroundPoint + sensors.closestGroundNormal, Color.blue); } else { // apply air move + tilt moveForce.upRotation = sensors.airBaseRotation; moveForce.tiltStrength = 1f; moveForce.tiltAngle = moveForce.airTiltResponse * input.move * parameters.maxAirTilt; moveForce.airMove = input.move * Vector3.forward * parameters.airMoveStrength * moveForce.airMoveResponse; //float inputTiltAmount = 45f * Mathf.Clamp01(sensors.inAirTime - 0.5f); // moveForce.tiltAngle = inputTiltAmount * input.move; // moveForce.airMove = input.move * Vector3.forward * parameters.airMoveStrength; } } } }
public static void ApplyAirForces(KobotoMoveForce moveForce, InputData input, KobotoSensor sensors, KobotoParameters parameters) { }
public virtual void UpdateKoboto(Koboto koboto, KobotoSensor sensor) { }