Impressive effect in "Exodo" with psuedo-3d sprites

Would anyone be able to help as to how to get a similar effect to this character “model”/sprite?

This is a 2d sprite based off your character model, which can be dynamically rotated to show different parts of your model, while still playing animations properly (Although in this game’s screenshot, the animations are on 2’s or 3’s). It’s hard to describe, but the following are a few places I’ve seen it in:

Exodo (Roblox game)
Ena: Dream BBQ, with the Taski Maiden (Free desktop game)

I love this effect, but I can only understand the theory of it (A model has 8 separate camera angles, and the current one on the sprite changes depending on the camera’s angle to the real model), and I struggle to implement it concretely. It would be a great help if anyone was able to help figure out how to apply such an effect in the Roblox engine.

Any help would be greatly appreciated!

I think there is a script that makes the real characters invisible and then uses ViewportFrame to create a fake character and rotates it in your GUI so it looks like it’s happening in the workspace.

2 Likes

Wow! That’s very interesting - My concern with this is how the GUI would be positioned to properly maintain positioning. As in, what would a formula for making it appear to be in the real world, maintaining the same position, look like? How would scaling work when you get further away vs getting closer. Still, I imagine it’s a method similar to this.

Thank you! I’ll look into this and see if I can get something working

I’m assuming they just slapped it onto a billboard gui and then used some dot products to find which angle to display

Edit: since the characters can clip through the wall, it most definitely is using billboard guis

1 Like
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local gui = script.Parent
local frame = gui:WaitForChild("ImageLabel")
local part = workspace:WaitForChild("Rig").Torso

RunService.RenderStepped:Connect(function()
	local partPosition = part.Position
	local screenPoint, onScreen = camera:WorldToViewportPoint(partPosition)

	if onScreen then

		frame.Position = UDim2.new(0, screenPoint.X, 0, screenPoint.Y)
		local distance = (camera.CFrame.Position - partPosition).Magnitude
		local scaleFactor = 10000 / distance
		local size = scaleFactor
		frame.Size = UDim2.new(0, size, 0, size)
		frame.Visible = true
	else
		frame.Visible = false
	end
end)

2 Likes