Cframe "offset"

Hello, i am currently making a system where you press a keycode then it will make a npc appear besides you (at the moment he appears in your humanoid rootpart, it’s supposed to be “offsetted”). can you tell me what is wrong with this code or why it is not working?

spawn(function()
			local goal = {}
			goal.CFrame = Stand.sHumanoidRootPart.CFrame*CFrame.new(2,0,2)
			local info = TweenInfo.new(.6)
			local tween = TweenService:Create(Stand.sHumanoidRootPart,info,goal)
			tween:Play()
			
			wait(.6)
			
			local weld = Instance.new("ManualWeld")
			weld.Parent = Stand.sHumanoidRootPart
			weld.Part0 = weld.Parent
			weld.Part1 = HumanoidRP
		end)

also tell me if i need to share the whole code

1 Like

Hey there, you’re using a manual weld with a setup like a weld constraint. Changing it back to weld constraint should fix it. Hope this helps.

ok
so that fixed the weld thing, but how do i make it be beside the character (atm its like underneath him alot)
tdlr: what coordinates should i use to make him be to the right side of the player (a little higher up than him too)

If the character has cancollide off then that .6 is gonna let it fall into the ground.

so what do i do to fix that?
(30 characters)

Remove the wait(0.6).
Simple as that.

Screen Shot 2020-05-17 at 11.48.16 PM
that is what happened…

You’re setting the cframe to the players rootpart cframe before you tween right? Also check if you have any weird welds.

yes i am
(30 charactersssssssss)

edit: the character that is supposed to be beside him has welds, dont see how that could effect it tho

edit2: also its supposed to tween from the players rootpart to the offset CFrame

Can you post your full function for me?

Okay that wait .6 was correct actually, im just dumb, my bad. The only thing I could think of at this point of why it would be in the ground is something with the CFrame offset.

oh… i don’t really know alot about math calculations and all that so should i try finding new values for the cframe offset?

edit: before i had it where the part where it sets the stands humanoidrootpart cframe too the player character humanoidrootpart cframe crossed out, it worked, now it shows no results when i removed the disabling, may that be a issue?

1 Like

If you’re making a stand, I personally recommend creating a WeldConstraint, setting your stand’s HumanoidRootPart to your exact character HumanoidRootPart CFrame or 1 stud behind it, welding it, and then making animations that are moved up and to the left (not to the right, if your game uses shiftlock the stand will be right in the way of the view).

This makes making new animations a lot easier, because you can animate in relation to where the stand user’s HumanoidRootPart is instead of making a bunch of tweens.

well, i did do that at first but when i tried animating it was a huge hassle, i also have tons of pre-made animations and i rather use a tween…

edit: going to sleep hopefully get a solution overnight

Okay so, I love it when I see jojo games being made without a overrused script base, lets fix this code and address certain codesmells.

YOU WILL HAVE TO USE ANIMATIONS.

This entire welding process will be simplified and will be fixed by using animations.
Download a animating plugin such as Moon Animator 2, make sure your stand is rigged (motor6ds).

Make sure to make your idle animation loop, I’m going to say it here TWEENS WILL NOT WORK.

			local weld = Instance.new("Weld") -- just use a normal weld
			weld.Parent = Stand.sHumanoidRootPart -- will be fine
			weld.Part0 = weld.Parent -- its okay
			weld.Part1 = HumanoidRP -- will work

This code is all fine and dandy, your issue is because you’re using a tween and wait() in your code.
I’m gonna provide you with some basic code that’s gonna fix this issue

-- completely obliterate the tweening here:
local standWeld = Instance.new("Weld")
standWeld.Part0 = HumanoidRP -- I've done the favor of making these your variable names
standWeld.Part1 = Stand.sHumanoidRootPart -- notice how im doing the properties first and not the parenting
-- this fixes replication lag is what happens if you do the reverse

standWeld.Parent = HumanoidRP

local idleTrack = Stand.sHumanoid:LoadAnimation(addYourIdleAnimHere) -- im assuming your stand has a Humanoid,
-- if it doesn't use an AnimationController object
idleTrack:Play() -- if this has a: LoadAnimation requires the Humanoid object to be a descendant of workspace error,
-- ill let you fix that

Alright, so this should fix your problem, another thing you mentioned is that you rather use a tween, this will look like a tween aswell, it wont appear staticly at the stand user’s back, it’ll smoothly move towards it.

EXTRA CODE SMELLS.

Code smells are basically pieces of code that indicate a bigger problem, lets get some things down.

spawn() and wait() are so unreliable, they should NEVER be in production code (aka the game)
So what’s the solution? The gold mine of a service, game:GetService("RunService").

FIXING WAIT.

We can easily fix up wait() by replacing it with a efficient function in our code,
Here’s a solution.

local function wait(n) -- local function will override wait()
   n = n or 0.01 -- this is a nifty code trick that replaces if X == nil then statements
   local heartbeat = game:GetService("RunService").Heartbeat -- heartbeat is widely used in coding, it's way more reliable
   local elapsedTime = 0 -- counter for the amount of time has passed since calling wait()
   
   while elapsedTime < n do
       local addThisToElapsedTime = heartbeat:Wait() -- heartbeat returns a delta (change in value if you dont know) that represents the elapsed time
       -- this also accounts for server lag!!
       elapsedTime = elapsedTime + addThisToElapsedTime
    end
end

Wow, that was alot, but I’m sure you can inform yourself by reading the comments.

FIXING SPAWN.

This one is really touchy. I’ve made a jojo game with spawn() handling stands, it. never. works.
So how do we even fix this?

We use something sort of expensive, a coding technique called fastSpawn
This works by using BindableEvents, they let you assign code to be executed when it’s fired, like
a remote event, but just for individual scripts.

So how do we implement this in code? Look.

local function spawn(func) -- again we overwrite just fine with local function
  local bindEvent = Instance.new("BindableEvent") -- create our event
  bindEvent.Event:Connect(func) -- assign our code to the event with :Connect()
  bindEvent:Fire() -- this executes the code IMMEDIATELY. which is why its expensive.
  bindEvent:Destroy() -- we do not need it anymore at all!!
  -- done.
end

Another hefty one, but the comments will help you entirely. NOW. I want to tell you something ESPECIALLY WITH JOJO GAMES. Do not. DO NOT. Make remotes for client-authorative stands.

“What do you mean?” you ask puzzled.

This is my biggest pet peeve, in the source code of A Bizarre Day, it uses client-authorative stands, this is so SO unsecure, it’s not okay to do this in production games. ABD also lets you supply hit sounds, so this isnt a matter of security aswell, it’s a matter of censoring bypassed hit sounds aswell.

What’s an example of this? Remotes like: “Damage1, Damage2, Spawn, etc…” Always have the server process this, I’m sure you can come up with a thing on your own.

SO? WHAT ELSE?

Nothing, good luck on your game, and be unique, dont have a game loop of roka, arrow, roka, arrow, GOOD STAND GOTTA TRADE IT, roka, arrow.

EDIT:

Also, you should completely replace your summon remote event with the .CharacterAdded event on Player. This can be spammed by exploiters, and adding a debounce as an argument will not work, you’re trusting the client faithfully, DONT TRUST THE CLIENT EVER EVER.

3 Likes

how do i change a key press to a character added (its meant to be press key summon, press key unsummon) without making stand always there, also wouldnt it stop working when someone dies?

Good question, it will NOT break when someone dies if you use .CharacterAdded on the player.

To your other question about summoning stands, you should add a Summon remote, that just controls the transparency, but keep the stand actually still there. I’m assuming you know how to use UserInputService for keypresses

So I don’t want to add an entire functioning code system, it’s meant for you to learn and be clever to devise your own plan. But a good basis will be this plan:

1. On Player.CharacterAdded do the stand spawning routine.
2. On the Summon remote being fired, tween the transparency to 1, but keep the stand there
3. On the client, listen for the keypress and fire the Summon remote.
4. And last but not least, ADD SANITY CHECKS. Do not let the client spam this remote, another reason why 
to just handle stands on the server.

Personally on my game, I use a modular object oriented system of stands, and I barely give the client control of their own stand for safety, it was such a hassle to DEVISE but in the end the module ended up being around 90 lines.

Only 90, my actual stand creator is around 1k lines, but that’s not the point. I just want you to know that having client authorative stands will set your game up for exploiting, and trust me, having tons of remotes is also really bad for understanding your game’s codebase.

It’s up to you, if you’re not ready to dive into that type of advanced scripting, you can do client-authorative stands, but just get ready for exploits.

Here’s a tradeoff table.

Server-Authorative stands == Better security, more latency issues.
Client-Authorative stands == Extremely worse security, extremely good ping.

EDIT: I realized that you may not know the difference between the server-authorative and client-authorative stands, so here

A Bizarre Day and Project Jojo: Client-Authorative Stands (so many exploiters)
Your Bizarre Adventure and jojoish game: Server-Authorative Stands (no exploiters, but latency)

2 Likes

I have a current stand system that does one of the things you listed, sanity checks. Used ticks to check when the remote was fired and if it was fired too fast, the client is kicked. My friend exploited on my game (to check) and it does indeed work nicely.

1 Like

Cool, that is also another way for the OP to learn, ticks and sanity checks go hand in hand all the time, I still stand strong on my point of server-authorative stands, but do whatever one you want and accept their trade-offs

1 Like