I’ve never intentionally used the Terrain object. I emphasize not intentionally because I use it quite frequently unintentionally – I end up with scripts erroring left and right because they searched through the workspace for parts and ended up picking up terrain because it’s a BasePart and then tried to change its parent or something which isn’t possible with Terrain. Not only do you have all of these wasted properties (e.g. BrickColor, Material, Reflectance, Transparency, Position, Rotation (I’m just going down the properties list and listing everything off)) – pretty much everything but Size is irrelevant, a waste of a property, and because Terrain extends BasePart it frequently gets accidentally picked up by scripts fetching parts from the game.
I’d imagine you had some reason for extending it from BasePart, but that has only caused trouble for the rest of us. Please don’t have Terrain inherit from BasePart and add all methods/properties you need to it directly. Yes, inheritance is a good way to re-use methods and properties, but inheriting an object also means that it should behave in at least a similar manner as that object and that anything that can be done to the object it inherits from can also be done to the inherited object. We cannot do everything we can to Terrain that we can do to BasePart, so please fix this.
Edit: I originally posted this because I selected parts by brick color and tried to group them and it failed because Terrain had gotten selected too, but it happened again
Terrain was made a subclass of BasePart when it was introduced so many years ago because it might be found (with Touched, FindPartOnRay, whatever…) by some scripts that would error by expecting it to be a part while it isn’t. These errors can be prevented by making it have the same properties.
It is not surprising that this strange design decision causes problems like yours, but at least those problems are in newer scripts, which can be terrain-aware. Overall I think it was a good idea.
Good? Maybe. Best? Certainly not. The best decision will be to make it not extend BasePart or any of its subclasses period so that none of these errors will happen in the first place.
Scripts might attempt to read or set properties of the terrain object, and break if it does not have these properties. The way that was chosen to avoid this is to give these properties to the terrain object but have them do nothing.
Nothing is going to be setting the properties of a terrain object though. If it isn’t a BasePart in the first place, scripts won’t be trying to set its properties at all.
"(with Touched, FindPartOnRay, whatever…) "
The terrain object is not passed through .Touched – you can’t touch it. The same with :FindPartOnRay – the terrain object isn’t picked up with FindPartOnRay either.
I do see why the properties inherited may not be beneficial for us. They’re not useable, so that’s all there is to that matter.
I would, however, like to point out that FindPartOnRay, Touched and other methods/events are being used to work with terrain - take for example the planets you see people making with terrain. Those use rays to determine the distance towards the ground - which is terrain. That, and I know I’ve been doing something related to terrain-touching in the past as well.
In the case where you want to mess with all parts of your game, simply add the ~30 characters it takes to write an if-statement.
I am however thinking that the behavior of :ClearAllChildren() on say Workspace throws an error when we get to Terrain. That could’ve been prevented.
Regardless of whether the decision was good or not, we can’t change this. And Touched/FindPartOnRay do work on Terrain.
I also find the practice of going through everything in workspace questionable. Why do you need this? (and why would you ClearAllChildren on workspace unless you’re exploiting?)
[quote] Regardless of whether the decision was good or not, we can’t change this. And Touched/FindPartOnRay do work on Terrain.
I also find the practice of going through everything in workspace questionable. Why do you need this? (and why would you ClearAllChildren on workspace unless you’re exploiting?) [/quote]
For changing to a different map, say you store a few maps in ServerStorage, or ReplicatedStorage, then clear the workspace, and move the new map there. Thats the only thing I could think of.
“I also find the practice of going through everything in workspace questionable.”
Select all medium stone grey colored parts in the game and parent them to workspace.Model
“Error cannot change parent of terrain”
Get loose parts in workspace and parent then to one model
“Error cannot change parent of terrain”
Select all plastic parts in workspace and parent them to workspace.LoosePlasticParts
“Error cannot change parent of terrain”
All of these cases happened in studio. When building I frequently switch around the parents of parts through the command bar so that they’re easier to manage, and I almost always end up forgetting about Terrain and I end up having to go back and re-execute with “and className ~= “Terrain”” I understand if you can’t change what it inherits now, but could you perhaps just silently fail for parent changing instead of throwing an error, only create the terrain object when there is actual terrain in the place, or have :IsA(“BasePart”) specifically return false for Terrain? Any one of those would help out a lot, but the first seems the most appropriate and would be the most helpful.
I know terrain works with FindPartOnRay, but I ended up getting nil,hitPosition when a ray intersected terrain (maybe I was doing it wrong), and I assumed that it wouldn’t fire .Touched either, but I guess I was wrong.