Rendering

In short

The project renders with URP. Everything, code-built primitives and imported models alike, gets the HomeRunDerby/BeanToon shader: flat colour bands, a warm rim and an inverted-hull outline. Post-processing, the sky and the ground textures are all built in code, so no scene or material asset is needed.

How it works

URP setup

  • Pipeline asset Assets/_Project/Settings/HomeRunDerby_URP.asset with renderer HomeRunDerby_Renderer.asset, assigned in Graphics and every Quality level.
  • Tools > Home Run Derby > Set Up URP (UrpSetup.Run) creates or reuses both assets, enables main-light and soft shadows, sets shadow distance, cascades and resolution, assigns them, and runs Unity’s Built-in to URP material converter on Standard materials. Safe to re-run.
  • SkyShaderInclude (runs on Editor load) adds Skybox/Procedural to Always Included Shaders, because the sky is built from code and a build would otherwise strip it.

BeanToon shader

Resources/Shaders/BeanToon.shader, in Resources so builds keep it and Shader.Find works. Passes: ForwardLit (colour bands, shadows, additional lights, fog, GPU instancing), Outline (LightMode SRPDefaultUnlit, back faces pushed out along normals), ShadowCaster, DepthOnly.

PropertyDefault
_BaseMap, _BaseColorwhite
_ShadowTint(0.58, 0.62, 0.82)
_Steps (1 to 4)2
_ShadeSoftness0.05
_RimColor, _RimPower, _RimStrength(1, 0.95, 0.85), 3.5, 0.22
_OutlineColor, _OutlineWidth(0.12, 0.09, 0.14), 0.012
_Cull2 (back)

Visuals helpers

MethodUse
CreateMaterial(color, outline = true)A toon material (outline 0.012 m). Falls back to URP Lit / Standard if the toon shader is missing. Sets _BaseColor, not Material.color.
CreateInstancedMaterial(color)For Graphics.DrawMeshInstanced (the crowd): no outline pass, instancing on.
Toonify(root)Swaps every material on an imported prefab for a toon copy that keeps its texture and tint (outline 0.006 m, 3 steps, softness 0.12). Used on bats, characters, park dressing, meteors and thumbnails.
CreateUnlitMaterial(color)URP Unlit (or Sprites/Default) for lines, trails, glows. Fed HDR colours (x 2.4 to 3.2) it glows through the bloom: the ball tracer and the fireworks do this (Hit Show, Cutscenes).
CreateTransparentMaterial(color)URP Unlit switched to its Transparent surface (alpha blend, no depth write, transparent queue); the colour’s alpha is the see-through amount. Used by the aim helper AimBat (Batting Feedback).
Primitive(...)A primitive with its collider removed.
CombinedCubes(...)Many cubes merged into one mesh, one draw call (grass stripes, stars).
Line(...)A LineRenderer with an unlit material.

Post-processing (PostFx.Setup)

Called once from GameRoot. Turns on post-processing and FXAA on the main camera and adds a global Volume with: bloom (intensity 0.3, threshold 1.1, scatter 0.6), vignette (0.18, smoothness 0.45), Neutral tonemapping, colour adjustments (saturation +18, contrast +6, post exposure +0.1). Does nothing without a render pipeline.

PostFx.SetMood(drain, darken, glow, vignette) lays a cutscene mood on top (all 0 = normal): drain 0..1 lerps saturation from +18 down to -85, darken lowers post exposure by that many stops, glow adds to bloom intensity, vignette adds to the vignette (clamped to 1). ResetMood() puts it back. Only OutroDirector uses it (the fireworks flash the bloom, GAME OVER drains the colour), and it resets it when the scene ends (Cutscenes).

Sky and light per park

BallparkBuilder.ApplyLighting sets the sun, then SkyBuilder.Apply retunes one Skybox/Procedural material from BallparkDefinition.sky, sets it as the skybox, and takes ambient light from the sky (AmbientMode.Skybox, DynamicGI.UpdateEnvironment).

SkyPresetSky tintGroundExposureAtmosphereSun sizeConvergence
ClearDay(0.45, 0.68, 1)(0.36, 0.46, 0.32)1.310.045
Overcast(0.62, 0.64, 0.68)(0.42, 0.42, 0.44)0.950.550.0156
Night(0.05, 0.07, 0.2)(0.02, 0.02, 0.04)0.281.30.038
Space(0.02, 0.02, 0.05)(0.06, 0.06, 0.07)0.70.080.083

Night and Space parks also get 260 stars; Space adds the Earth. Night stadiums get four spotlight towers (Ballpark Building).

Ground textures

ParkTextures generates tiling textures in code: PatchyGrass(color) (512 px, one tile per 100 m), InfieldDirt() (256 px, one tile per 3 m) and Regolith(color, craters) for the moon. Colours are banded to match the toon shading; results are cached.

Camera

CameraRig (on the main camera) has the batter view (position (0, 1.25, -2.7), looking at (0, 0.1, 12), FOV 55), a menu view, cinematic shots, an orbit (Customize) and follow. SetCinematic(position, lookAt, fov, rollDeg) also banks the view, which the TV-style flight camera uses to lean into pans (Hit Show). The cutscene shots come from Intro/IntroCamera and are applied with SetCinematic too.

Numbers

WhatValueWhere to tune
Shadow distance160 mUrpSetup.ShadowDistance
Shadow cascades3UrpSetup.ShadowCascades
Main light shadow map2048UrpSetup.ShadowResolution
Sun by day50 deg pitch, intensity 1.1, warm whiteBallparkBuilder.ApplyLighting
Moon at night25 deg pitch, intensity 0.25, cool blueBallparkBuilder.ApplyLighting
Ambient intensity1 (night 0.7)SkyBuilder.Apply
Batter view FOV55CameraRig.BatterViewFov

In the code

FileWhat it does
Scripts/Core/Visuals.csMaterial and geometry helpers.
Scripts/Core/PostFx.csThe global volume; SetMood / ResetMood.
Scripts/Core/CameraRig.csCamera views, including the banked SetCinematic.
Resources/Shaders/BeanToon.shaderThe toon shader.
Scripts/Ballparks/SkyBuilder.csSky presets and ambient.
Scripts/Ballparks/ParkTextures.csGenerated ground textures.
Editor/UrpSetup.csSet Up URP.
Editor/SkyShaderInclude.csKeeps the sky shader in builds.

Gotchas

Keep instancing in BeanToon

The crowd is drawn with Graphics.DrawMeshInstanced. If an edit drops multi_compile_instancing or the instance IDs from any pass, every fan lands on one spot and the crowd vanishes.

  • BallShadow is still an opaque disc. Since #46 one runtime material is transparent (AimBat, through CreateTransparentMaterial). URP’s Unlit picks its transparent surface with a shader keyword, and keyword variants no material asset uses can be stripped from builds; whether the transparent variant survives in a Windows build is not determined from the code, so check the aim helper in a build.
  • If Skybox/Procedural is missing at runtime, SkyBuilder falls back to a flat background colour.
  • Floodlight spots cast no shadows; the moon (the directional light) does.