Devlog #08 - Implementing Spectator Player
Introduction:
As per the next plan, the most unique aspect of our board game is to let the spectator player play as well during an ongoing battle. This is the key to forming alliances while the game lasts. We were quite focused on the balance aspect, hence we are currently not letting players who spectate do damage to the arena players, although we wanted something that could be advantageous enough to give value to forming alliances. Hence, we will currently be giving a movement debuff of 40 percent, and we will mostly alter this value during the playtesting phase.
Setting up a model:
Since we are developing a base model that will be replaced by the player's avatar and we are focusing on developing the mechanics of the game. I decided to reuse as much things as possible, So I could develop the mechanics as fast as possible. The model reuses aspects of the Arena player.

Here we have 2 empty game objects, FireStartingPoint, which is where we spawn our bullet or projectile, and AimTarget, which is where our bullet is supposed to go. AimTarget is new in this model because we decided to make the projectile shoot towards the sky and fall down on the player, hence avoiding as many obstacles, since the spectators can't move. So we needed this target to calculate the amount of distance to cover, and hence calculate the velocity that needs to be applied. Also, we attached a crosshair to this point to let players be more accurate about where they are shooting. There is also one more advantage to this approach, which is that we could easily incorporate controller support since we use a crosshair in-game, which is already done

Visual Feedback:
In this game, we also have a projectile preview script that uses the 2 empty child objects to follow the same calculation and get arc points. These points are then passed to the line renderer component to draw a projectile trajectory to aid players in their accuracy. This component is used to disable the line renderer when the projectile is not ready to fire, hence acting as a visual indicator of when a player can shoot.
void Update() { if (firePoint == null || aimTarget == null) { lr.enabled = false; return; } Vector3 start = firePoint.position; Vector3 end = aimTarget.position; if (Vector3.Distance(start, lastFirePointPos) < 0.01f && Vector3.Distance(end, lastAimTargetPos) < 0.01f) { return; } lastFirePointPos = start; lastAimTargetPos = end; // Check if target is too close float distance = Vector3.Distance(new Vector3(start.x, 0, start.z), new Vector3(end.x, 0, end.z)); if (distance < minDistance) { lr.enabled = false; return; } lr.enabled = true; Vector3[] points = new Vector3[resolution]; // Clamp target Y to prevent extreme downward aim if (end.y < start.y - 1f) { end.y = start.y - 1f; } float gravity = Mathf.Abs(Physics.gravity.y); // Calculate direction and vertical distance Vector3 direction = new Vector3(end.x - start.x, 0f, end.z - start.z); float horizontalDistance = direction.magnitude; float verticalDistance = end.y - start.y; // Calculate time to apex and descent float timeToApex = Mathf.Sqrt(2 * arcHeight / gravity); float descendHeight = Mathf.Max(arcHeight - verticalDistance, 0.1f); float timeFromApex = Mathf.Sqrt(2 * descendHeight / gravity); float totalTime = Mathf.Clamp(timeToApex + timeFromApex, 0.1f, 5f); // Calculate velocities Vector3 horizontalVelocity = direction.normalized * (horizontalDistance / totalTime); float verticalVelocity = Mathf.Sqrt(2 * gravity * arcHeight); Vector3 initialVelocity = horizontalVelocity + Vector3.up * verticalVelocity; // Generate arc points for (int i = 0; i < resolution; i++) { float t = (i / (float)(resolution - 1)) * totalTime; Vector3 point = start + initialVelocity * t + 0.5f * Physics.gravity * t * t; points[i] = point; } lr.positionCount = resolution; lr.SetPositions(points); }
This script is done in ProjectileArcPreview.cs
The next visual feedback is in the MortarProjectile Script, which uses a trail renderer component to render a trail that acts as a visual indicator of the impending debuff coming your way.

The MortarProjectile script also stores the slow amount and the duration, which is processed and accordingly applied to the arena player. And when the collision is triggered, a small particle effect is played to let the player know they are being debuffed.
Additionally, I have made changes to the ArenaPlayerRPC script to process this slow effect and have a blue tint on the character to act as a visual indicator of the player being slowed
Final Output:
Hence, using these steps, we have successfully implemented the spectator player mechanics that could be controlled using both keyboard and mouse, and a controller.
References:
[1] Unity Trail Renderer component reference: https://docs.unity3d.com/Manual/class-TrailRenderer.html
[2] Unity.Line Renderer component reference: https://docs.unity3d.com/Manual/class-LineRenderer.html
[3] Use of Generative AI:
prompt - "What are the mathematical calculations to find the velocity to be applied for an object to go from point A to point B, after reaching a certain apex height?"
Dice & Domination
Party board game
Status | In development |
Author | Akhil Mathew |
Genre | Strategy |
More posts
- Devlog #07 - Multiplayer Battle Mode Implemented9 days ago
- Devlog #06 - Implementing Enemy Turret9 days ago
- Devlog #05 - Implementing Health and Damage System15 days ago
- Devlog #04 - Implementing Shooting [Part-B] - Crosshair Implemented17 days ago
- Devlog #03 - Implementing Shooting [Part-A] - Mechanices Implemented17 days ago
- Devlog #02 - Implementing Dash Mechanics45 days ago
- Devlog #01 - New Input Manager50 days ago
Leave a comment
Log in with itch.io to leave a comment.